<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.4">
<meta name="author" content="Jens Wilke">
<title>cache2k User Guide</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
<style>
/* Stylesheet for CodeRay to match GitHub theme | MIT License | http://foundation.zurb.com */
/*pre.CodeRay {background-color:#f7f7f8;}*/
.CodeRay .line-numbers{border-right:1px solid #d8d8d8;padding:0 0.5em 0 .25em}
.CodeRay span.line-numbers{display:inline-block;margin-right:.5em;color:rgba(0,0,0,.3)}
.CodeRay .line-numbers strong{color:rgba(0,0,0,.4)}
table.CodeRay{border-collapse:separate;border-spacing:0;margin-bottom:0;border:0;background:none}
table.CodeRay td{vertical-align: top;line-height:1.45}
table.CodeRay td.line-numbers{text-align:right}
table.CodeRay td.line-numbers>pre{padding:0;color:rgba(0,0,0,.3)}
table.CodeRay td.code{padding:0 0 0 .5em}
table.CodeRay td.code>pre{padding:0}
.CodeRay .debug{color:#fff !important;background:#000080 !important}
.CodeRay .annotation{color:#007}
.CodeRay .attribute-name{color:#000080}
.CodeRay .attribute-value{color:#700}
.CodeRay .binary{color:#509}
.CodeRay .comment{color:#998;font-style:italic}
.CodeRay .char{color:#04d}
.CodeRay .char .content{color:#04d}
.CodeRay .char .delimiter{color:#039}
.CodeRay .class{color:#458;font-weight:bold}
.CodeRay .complex{color:#a08}
.CodeRay .constant,.CodeRay .predefined-constant{color:#008080}
.CodeRay .color{color:#099}
.CodeRay .class-variable{color:#369}
.CodeRay .decorator{color:#b0b}
.CodeRay .definition{color:#099}
.CodeRay .delimiter{color:#000}
.CodeRay .doc{color:#970}
.CodeRay .doctype{color:#34b}
.CodeRay .doc-string{color:#d42}
.CodeRay .escape{color:#666}
.CodeRay .entity{color:#800}
.CodeRay .error{color:#808}
.CodeRay .exception{color:inherit}
.CodeRay .filename{color:#099}
.CodeRay .function{color:#900;font-weight:bold}
.CodeRay .global-variable{color:#008080}
.CodeRay .hex{color:#058}
.CodeRay .integer,.CodeRay .float{color:#099}
.CodeRay .include{color:#555}
.CodeRay .inline{color:#000}
.CodeRay .inline .inline{background:#ccc}
.CodeRay .inline .inline .inline{background:#bbb}
.CodeRay .inline .inline-delimiter{color:#d14}
.CodeRay .inline-delimiter{color:#d14}
.CodeRay .important{color:#555;font-weight:bold}
.CodeRay .interpreted{color:#b2b}
.CodeRay .instance-variable{color:#008080}
.CodeRay .label{color:#970}
.CodeRay .local-variable{color:#963}
.CodeRay .octal{color:#40e}
.CodeRay .predefined{color:#369}
.CodeRay .preprocessor{color:#579}
.CodeRay .pseudo-class{color:#555}
.CodeRay .directive{font-weight:bold}
.CodeRay .type{font-weight:bold}
.CodeRay .predefined-type{color:inherit}
.CodeRay .reserved,.CodeRay .keyword {color:#000;font-weight:bold}
.CodeRay .key{color:#808}
.CodeRay .key .delimiter{color:#606}
.CodeRay .key .char{color:#80f}
.CodeRay .value{color:#088}
.CodeRay .regexp .delimiter{color:#808}
.CodeRay .regexp .content{color:#808}
.CodeRay .regexp .modifier{color:#808}
.CodeRay .regexp .char{color:#d14}
.CodeRay .regexp .function{color:#404;font-weight:bold}
.CodeRay .string{color:#d20}
.CodeRay .string .string .string{background:#ffd0d0}
.CodeRay .string .content{color:#d14}
.CodeRay .string .char{color:#d14}
.CodeRay .string .delimiter{color:#d14}
.CodeRay .shell{color:#d14}
.CodeRay .shell .delimiter{color:#d14}
.CodeRay .symbol{color:#990073}
.CodeRay .symbol .content{color:#a60}
.CodeRay .symbol .delimiter{color:#630}
.CodeRay .tag{color:#008080}
.CodeRay .tag-special{color:#d70}
.CodeRay .variable{color:#036}
.CodeRay .insert{background:#afa}
.CodeRay .delete{background:#faa}
.CodeRay .change{color:#aaf;background:#007}
.CodeRay .head{color:#f8f;background:#505}
.CodeRay .insert .insert{color:#080}
.CodeRay .delete .delete{color:#800}
.CodeRay .change .change{color:#66f}
.CodeRay .head .head{color:#f4f}
</style>
</head>
<body class="book toc2 toc-left">
<div id="header">
<h1>cache2k User Guide</h1>
<div class="details">
<span id="author" class="author">Jens Wilke</span><br>
<span id="revnumber">version 1.0.2.Final</span>
</div>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#about">1. About</a>
<ul class="sectlevel2">
<li><a href="#versioning">1.1. Versioning</a></li>
<li><a href="#how-to-read-the-documentation">1.2. How to read the documentation</a></li>
<li><a href="#copyright">1.3. Copyright</a></li>
</ul>
</li>
<li><a href="#getting-started">2. Getting Started</a>
<ul class="sectlevel2">
<li><a href="#getting-started">2.1. Obtaining cache2k</a></li>
<li><a href="#using-a-cache">2.2. Using a Cache</a></li>
<li><a href="#cache-aside">2.3. Cache Aside</a></li>
<li><a href="#read-through">2.4. Read Through</a></li>
<li><a href="#using-null-values">2.5. Using Null Values</a></li>
<li><a href="#composite-keys">2.6. Composite Keys</a></li>
<li><a href="#keys-need-to-be-immutable">2.7. Keys Need to be Immutable</a></li>
<li><a href="#mutating-values">2.8. Mutating Values</a></li>
<li><a href="#exceptions-and-caching">2.9. Exceptions and Caching</a></li>
<li><a href="#don-t-panic">2.10. Don&#8217;t Panic!</a></li>
</ul>
</li>
<li><a href="#types">3. Types</a>
<ul class="sectlevel2">
<li><a href="#constructing-a-cache-with-generic-types">3.1. Constructing a Cache with Generic Types</a></li>
<li><a href="#constructing-a-cache-without-generic-types">3.2. Constructing a Cache without Generic Types</a></li>
<li><a href="#key-type">3.3. Key Type</a></li>
<li><a href="#value-type">3.4. Value Type</a></li>
<li><a href="#untyped-caches">3.5. Untyped Caches</a></li>
<li><a href="#future-enhancements">3.6. Future Enhancements</a></li>
</ul>
</li>
<li><a href="#atomic-operations">4. Atomic Operations</a>
<ul class="sectlevel2">
<li><a href="#example">4.1. Example</a></li>
<li><a href="#built-in-atomic-operations">4.2. Built-in Atomic Operations</a></li>
<li><a href="#entry-processor">4.3. Entry Processor</a></li>
</ul>
</li>
<li><a href="#loading-read-through">5. Loading / Read Through</a>
<ul class="sectlevel2">
<li><a href="#benefits-of-read-through-operation">5.1. Benefits of Read Through Operation</a></li>
<li><a href="#defining-a-loader">5.2. Defining a Loader</a></li>
<li><a href="#advanced-loader">5.3. Advanced Loader</a></li>
<li><a href="#using-lambda-loaders-in-java-8">5.4. Using Lambda Loaders in Java 8</a></li>
<li><a href="#prefetching">5.5. Prefetching</a></li>
<li><a href="#invalidating">5.6. Invalidating</a></li>
<li><a href="#transparent-access">5.7. Transparent Access</a></li>
</ul>
</li>
<li><a href="#expiry-and-refresh">6. Expiry and Refresh</a>
<ul class="sectlevel2">
<li><a href="#specifying-an-expiry-duration">6.1. Specifying an Expiry Duration</a></li>
<li><a href="#variable-expiry">6.2. Variable Expiry</a></li>
<li><a href="#lagging-expiry">6.3. Lagging Expiry</a></li>
<li><a href="#sharp-expiry">6.4. Sharp Expiry</a></li>
<li><a href="#loader-exceptions-and-expiry">6.5. Loader Exceptions and Expiry</a></li>
<li><a href="#resetting-the-expiry-of-a-cache-value">6.6. Resetting the Expiry of a Cache Value</a></li>
<li><a href="#wall-clock-and-clock-skew">6.7. Wall Clock and Clock Skew</a></li>
</ul>
</li>
<li><a href="#refresh-ahead">7. Refresh Ahead</a>
<ul class="sectlevel2">
<li><a href="#setup">7.1. Setup</a></li>
<li><a href="#semantics">7.2. Semantics</a></li>
<li><a href="#sharp-expiry-vs-refresh-ahead">7.3. Sharp Expiry vs. Refresh Ahead</a></li>
<li><a href="#rationale-no-separate-refresh-timing-parameter">7.4. Rationale: No separate refresh timing parameter?</a></li>
<li><a href="#future-outlook">7.5. Future Outlook</a></li>
</ul>
</li>
<li><a href="#null-values">8. Null Values</a>
<ul class="sectlevel2">
<li><a href="#the-pros-and-cons-of-nulls">8.1. The Pros and Cons of Nulls</a></li>
<li><a href="#negative-result-caching">8.2. Negative Result Caching</a></li>
<li><a href="#alternatives">8.3. Alternatives</a></li>
<li><a href="#default-behavior">8.4. Default Behavior</a></li>
<li><a href="#how-to-enable-null-values">8.5. How to Enable Null Values</a></li>
<li><a href="#how-to-operate-with-null-values">8.6. How to Operate with Null Values</a></li>
<li><a href="#loader-and-null-values">8.7. Loader and Null Values</a></li>
<li><a href="#performance">8.8. Performance</a></li>
<li><a href="#rationale">8.9. Rationale</a></li>
</ul>
</li>
<li><a href="#resilience-and-exceptions">9. Exceptions and Resilience</a>
<ul class="sectlevel2">
<li><a href="#behavior">9.1. Behavior</a></li>
<li><a href="#retry">9.2. Retry</a></li>
<li><a href="#exception-propagation">9.3. Exception Propagation</a></li>
<li><a href="#invalidating-2">9.4. Invalidating</a></li>
<li><a href="#entry-status-and-code-containskey-code">9.5. Entry Status and <code>containsKey</code></a></li>
<li><a href="#configuration-options">9.6. Configuration options</a></li>
<li><a href="#examples">9.7. Examples</a></li>
<li><a href="#custom-resilience-policy">9.8. Custom resilience policy</a></li>
<li><a href="#debugging">9.9. Debugging</a></li>
</ul>
</li>
<li><a href="#event-listeners">10. Event Listeners</a>
<ul class="sectlevel2">
<li><a href="#listening-to-events">10.1. Listening to Events</a></li>
<li><a href="#async-listeners">10.2. Async Listeners</a></li>
</ul>
</li>
<li><a href="#xml-configuration">11. Configuration via XML</a>
<ul class="sectlevel2">
<li><a href="#using-the-xml-configuration">11.1. Using the XML Configuration</a></li>
<li><a href="#combine-programmatic-and-xml-configuration">11.2. Combine Programmatic and XML Configuration</a></li>
<li><a href="#reference-documentation">11.3. Reference Documentation</a></li>
<li><a href="#rationale-2">11.4. Rationale</a></li>
</ul>
</li>
<li><a href="#logging">12. Logging</a>
<ul class="sectlevel2">
<li><a href="#supported-log-infrastructure">12.1. Supported Log Infrastructure</a></li>
<li><a href="#wiring-a-custom-log-target">12.2. Wiring a Custom Log Target</a></li>
</ul>
</li>
<li><a href="#statistics">13. Statistics</a>
<ul class="sectlevel2">
<li><a href="#jmx-metrics">13.1. JMX Metrics</a></li>
<li><a href="#code-tostring-code-output">13.2. <code>toString()</code> Output</a></li>
<li><a href="#accuracy-overhead-and-performance">13.3. Accuracy, Overhead and Performance</a></li>
<li><a href="#internal-statistics">13.4. Internal Statistics</a></li>
<li><a href="#noteworthy-metrics">13.5. Noteworthy Metrics</a></li>
</ul>
</li>
<li><a href="#android">14. Android</a>
<ul class="sectlevel2">
<li><a href="#usage">14.1. Usage</a></li>
<li><a href="#xml-configuration-2">14.2. XML Configuration</a></li>
</ul>
</li>
<li><a href="#jcache">15. JCache</a>
<ul class="sectlevel2">
<li><a href="#maven-dependencies">15.1. Maven Dependencies</a></li>
<li><a href="#getting-started-with-the-jcache-api">15.2. Getting Started with the JCache API</a></li>
<li><a href="#configuration">15.3. Configuration</a></li>
<li><a href="#control-additional-jcache-semantics">15.4. Control Additional JCache Semantics</a></li>
<li><a href="#implementation-details">15.5. Implementation Details</a></li>
<li><a href="#performance-2">15.6. Performance</a></li>
<li><a href="#compliance-testing">15.7. Compliance Testing</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="about"><a class="anchor" href="#about"></a>1. About</h2>
<div class="sectionbody">
<div class="paragraph">
<p>cache2k is a compact in-process cache implementation that has the following main design goals:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Performance</dt>
<dd>
<p>fundamentally different eviction algorithm to allow fast and lock free reads</p>
</dd>
<dt class="hdlist1">Ease of use</dt>
<dd>
<p>defined API, solve common problems with one configuration option</p>
</dd>
<dt class="hdlist1">Compact and modular</dt>
<dd>
<p>small core size</p>
</dd>
</dl>
</div>
<div class="sect2">
<h3 id="versioning"><a class="anchor" href="#versioning"></a>1.1. Versioning</h3>
<div class="paragraph">
<p>The JBoss versioning scheme is followed (<a href="https://developer.jboss.org/wiki/JBossProjectVersioning" class="bare">https://developer.jboss.org/wiki/JBossProjectVersioning</a>).
Furthermore, a Tick-Tock scheme is used to mark development releases. Examples:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">1.0.0.Final</dt>
<dd>
<p>Major version.</p>
</dd>
<dt class="hdlist1">1.0.1.Final</dt>
<dd>
<p>Service release. Should be binary compatible to previous release.</p>
</dd>
<dt class="hdlist1">1.1.0.Beta</dt>
<dd>
<p><strong>Odd minor version</strong>, development version. A beta version may be used in production, but
additional features may still change the API and may not completely tested.</p>
</dd>
<dt class="hdlist1">1.2.0.Final</dt>
<dd>
<p><strong>Even minor version</strong>, stable release, new features and compatible changes to the previous version.
Not be strictly binary compatible to the previous stable release. Interfaces not meant for
extension may get new methods.</p>
</dd>
<dt class="hdlist1">2.0.0.Final</dt>
<dd>
<p>New Major version, adds and removes features, may have incompatible changes to the previous version.</p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="how-to-read-the-documentation"><a class="anchor" href="#how-to-read-the-documentation"></a>1.2. How to read the documentation</h3>
<div class="paragraph">
<p>The documentation is intended as a overview guide through the functionality of cache2k and will help
you discover every important feature. At some points rationale or background
information is given. It is not complete. You will find additional information in the API JavaDoc,
in examples, and in the test cases.</p>
</div>
<div class="paragraph">
<p>A <a href="user-guide.pdf">cache2k User Guide PDF Version</a> is available as well.</p>
</div>
</div>
<div class="sect2">
<h3 id="copyright"><a class="anchor" href="#copyright"></a>1.3. Copyright</h3>
<div class="paragraph">
<p>The documentation is licensed under the terms of <a href="https://creativecommons.org/licenses/by/4.0/">CC BY 4.0</a>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="getting-started"><a class="anchor" href="#getting-started"></a>2. Getting Started</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="getting-started"><a class="anchor" href="#getting-started"></a>2.1. Obtaining cache2k</h3>
<div class="paragraph">
<p>The latest cache2k version is available on maven central. The recommended way to include it
in your project is to add the following dependencies:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;properties&gt;</span>
      <span class="tag">&lt;cache2k-version&gt;</span>1.0.2.Final<span class="tag">&lt;/cache2k-version&gt;</span>
    <span class="tag">&lt;/properties&gt;</span>

    <span class="tag">&lt;dependencies&gt;</span>
      <span class="tag">&lt;dependency&gt;</span>
        <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
        <span class="tag">&lt;artifactId&gt;</span>cache2k-api<span class="tag">&lt;/artifactId&gt;</span>
        <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
        <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
      <span class="tag">&lt;/dependency&gt;</span>
      <span class="tag">&lt;dependency&gt;</span>
        <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
        <span class="tag">&lt;artifactId&gt;</span>cache2k-all<span class="tag">&lt;/artifactId&gt;</span>
        <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
        <span class="tag">&lt;scope&gt;</span>runtime<span class="tag">&lt;/scope&gt;</span>
      <span class="tag">&lt;/dependency&gt;</span>
    <span class="tag">&lt;/dependencies&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This will add the single <code>cache2k-all</code> JAR file to your application deliverable. For compiling and development
the <code>cache2k-api</code> is included which contains API classes only. The above requires at least a <code>Java SE 6</code> compatible
runtime. For usage with Android, see the <a href="#android">Android</a> chapter.</p>
</div>
</div>
<div class="sect2">
<h3 id="using-a-cache"><a class="anchor" href="#using-a-cache"></a>2.2. Using a Cache</h3>
<div class="paragraph">
<p>For starting with cache2k, let&#8217;s construct a cache that looks up the preferred airline for one of our frequent flight
routes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt; cache = <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt;() {}
      .name(<span class="string"><span class="delimiter">&quot;</span><span class="content">routeToAirline</span><span class="delimiter">&quot;</span></span>)
      .eternal(<span class="predefined-constant">true</span>)
      .entryCapacity(<span class="integer">100</span>)
      .build();
    <span class="comment">// populate with our favorites</span>
    cache.put(<span class="string"><span class="delimiter">&quot;</span><span class="content">MUC-SFO</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Yeti Jet</span><span class="delimiter">&quot;</span></span>);
    cache.put(<span class="string"><span class="delimiter">&quot;</span><span class="content">SFO-LHR</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Quality Air</span><span class="delimiter">&quot;</span></span>);
    cache.put(<span class="string"><span class="delimiter">&quot;</span><span class="content">LHR-SYD</span><span class="delimiter">&quot;</span></span>, <span class="string"><span class="delimiter">&quot;</span><span class="content">Grashopper Lifting</span><span class="delimiter">&quot;</span></span>);
    <span class="comment">// query the cache</span>
    <span class="predefined-type">String</span> route = <span class="string"><span class="delimiter">&quot;</span><span class="content">LHR-MUC</span><span class="delimiter">&quot;</span></span>;
    <span class="keyword">if</span> (cache.containsKey(route)) {
      <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">We have a favorite airline for the route </span><span class="delimiter">&quot;</span></span> + route);
    } <span class="keyword">else</span> {
      <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">We don't have a favorite airline for the route </span><span class="delimiter">&quot;</span></span> + route);
    }
    <span class="predefined-type">String</span> airline = cache.peek(route);
    <span class="keyword">if</span> (airline != <span class="predefined-constant">null</span>) {
      <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">Let's go with </span><span class="delimiter">&quot;</span></span> + airline);
    } <span class="keyword">else</span> {
      <span class="predefined-type">System</span>.out.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">You need to find one yourself</span><span class="delimiter">&quot;</span></span>);
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>To obtain the cache a new <code>Cache2kBuilder</code> is created. Mind the trailing <code>{}</code>. There are a dozens of
options that can alter the behavior of a cache. In the example above the cache gets a name and is instructed
to keep entries forever via <code>eternal(true)</code>. A name needs to be unique and may be used to find and apply additional
configuration parameters and to make statistics available via JMX. Find the details about naming a cache
at in JavaDoc of <a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/Cache2kBuilder.html#name-java.lang.String-"><code>Cache2kBuilder.name()</code></a>.</p>
</div>
<div class="paragraph">
<p>The cache has a maximum capacity of 100 entries. When the limit is reached an entry is automatically removed that
 is not used very often. This is called eviction.</p>
</div>
<div class="paragraph">
<p>In the example <code>Cache.put()</code> is used to store values. The cache content is queried with <code>Cache.peek()</code> and
<code>Cache.containsKey()</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="cache-aside"><a class="anchor" href="#cache-aside"></a>2.3. Cache Aside</h3>
<div class="paragraph">
<p>Let&#8217;s consider we have an operation called <code>findFavoriteAirline()</code>, that checks all our previous flights
and finds the airline we liked the most. If we never did fly on that route it will ask all our friends.
 Of course this is very time consuming, so we first ask the cache, whether something for that flight
 route is already known, if not, we call the expensive operation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt; routeToAirline = <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt;() {}
      .name(<span class="string"><span class="delimiter">&quot;</span><span class="content">routeToAirline</span><span class="delimiter">&quot;</span></span>)
      .build();

    <span class="directive">private</span> <span class="predefined-type">String</span> findFavoriteAirline(<span class="predefined-type">String</span> origin, <span class="predefined-type">String</span> destination) {
      <span class="comment">// expensive operation to find the best airline for this route</span>
      <span class="comment">// for example, ask all friends...</span>
    }

    <span class="directive">public</span> <span class="predefined-type">String</span> lookupFavoirteAirline(<span class="predefined-type">String</span> origin, <span class="predefined-type">String</span> destination) {
      <span class="predefined-type">String</span> route = origin + <span class="string"><span class="delimiter">&quot;</span><span class="content">-</span><span class="delimiter">&quot;</span></span> + destination;
      <span class="predefined-type">String</span> airline = routeToAirline.peek(route);
      <span class="keyword">if</span> (airline == <span class="predefined-constant">null</span>) {
        airline = findFavoriteAirline(origin, destination);
        routeToAirline.put(route, airline);
      }
      <span class="keyword">return</span> airline;
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The above pattern is called <em>cache aside</em>.</p>
</div>
</div>
<div class="sect2">
<h3 id="read-through"><a class="anchor" href="#read-through"></a>2.4. Read Through</h3>
<div class="paragraph">
<p>An alternative way to use the cache is the so called <em>read through</em> operation. The cache configuration
gets customized with a loader, so the cache knows how to retrieve missing values.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">  Cache&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt; routeToAirline = <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt;() {}
    .name(<span class="string"><span class="delimiter">&quot;</span><span class="content">routeToAirline</span><span class="delimiter">&quot;</span></span>)
    .loader(<span class="keyword">new</span> CacheLoader&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt;() {
      <span class="annotation">@Override</span>
      <span class="directive">public</span> <span class="predefined-type">String</span> load(<span class="directive">final</span> <span class="predefined-type">String</span> key) <span class="directive">throws</span> <span class="exception">Exception</span> {
        <span class="predefined-type">String</span><span class="type">[]</span> port = key.split(<span class="string"><span class="delimiter">&quot;</span><span class="content">-</span><span class="delimiter">&quot;</span></span>);
        <span class="keyword">return</span> findFavoriteAirline(port[<span class="integer">0</span>], port[<span class="integer">1</span>]);
      }
    })
    .build();

  <span class="directive">private</span> <span class="predefined-type">String</span> findFavoriteAirline(<span class="predefined-type">String</span> origin, <span class="predefined-type">String</span> destination) {
    <span class="comment">// expensive operation to find the best airline for this route</span>
  }

  <span class="directive">public</span> <span class="predefined-type">String</span> lookupFavoirteAirline(<span class="predefined-type">String</span> origin, <span class="predefined-type">String</span> destination) {
    <span class="predefined-type">String</span> route = origin + <span class="string"><span class="delimiter">&quot;</span><span class="content">-</span><span class="delimiter">&quot;</span></span> + destination;
    <span class="keyword">return</span> routeToAirline.get(route);
  }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we use <code>Cache.get</code> to request a value from the cache, which transparently invokes
the loader and populates the cache, if the requested value is missing. Using a cache in read through
mode has various advantages:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>No boilerplate code as in cache aside</p>
</li>
<li>
<p>Protection against the cache stampede (See <a href="https://en.wikipedia.org/wiki/Cache_stampede">Wikipedia: Cache Stampede</a>)</p>
</li>
<li>
<p>Automatic refreshing of expired values is possible (<a href="#refresh">refresh ahead</a>)</p>
</li>
<li>
<p>Built-in exception handling like suppression and retries (see <a href="#resiliance">Resilience</a> chapter)</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="using-null-values"><a class="anchor" href="#using-null-values"></a>2.5. Using Null Values</h3>
<div class="paragraph">
<p>The simple example has a major design problem. What happens if no airline is found? Typically caches don&#8217;t allow
<code>null</code> values. When you try to store or load a <code>null</code> value into cache2k you will get a <code>NullPointerException</code>.
Sometimes it is better to avoid <code>null</code> values, in our example we could return a list of favorite airlines which may
 be empty.</p>
</div>
<div class="paragraph">
<p>In case a <code>null</code> value is the best choice, it is possible to store it in cache2k by enabling it with
<code>permitNullValues(true)</code>. See the <a href="#null">Null Values chapter</a> for more details.</p>
</div>
</div>
<div class="sect2">
<h3 id="composite-keys"><a class="anchor" href="#composite-keys"></a>2.6. Composite Keys</h3>
<div class="paragraph">
<p>In the example the key is constructed by concatenating the origin and destination airport. This is ineffective for
several reasons. The string concatenation allocates two temporary objects (the <code>StringBuilder</code> and
its character array); if we need the two parts again we have to split the string again. A better way
is to define a dedicated class for the cache key that is a tuple of origin and destination.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">  <span class="directive">public</span> <span class="directive">final</span> <span class="type">class</span> <span class="class">Route</span> {
    <span class="directive">private</span> <span class="predefined-type">String</span> origin;
    <span class="directive">private</span> <span class="predefined-type">String</span> destination;

    <span class="directive">public</span> Route(<span class="directive">final</span> <span class="predefined-type">String</span> origin, <span class="directive">final</span> <span class="predefined-type">String</span> destination) {
      <span class="local-variable">this</span>.destination = destination;
      <span class="local-variable">this</span>.origin = origin;
    }

    <span class="directive">public</span> <span class="predefined-type">String</span> getOrigin() {
      <span class="keyword">return</span> origin;
    }

    <span class="directive">public</span> <span class="predefined-type">String</span> getDestination() {
      <span class="keyword">return</span> destination;
    }

    <span class="annotation">@Override</span>
    <span class="directive">public</span> <span class="type">boolean</span> equals(<span class="directive">final</span> <span class="predefined-type">Object</span> other) {
      <span class="keyword">if</span> (<span class="local-variable">this</span> == other) <span class="keyword">return</span> <span class="predefined-constant">true</span>;
      <span class="keyword">if</span> (other == <span class="predefined-constant">null</span> || getClass() != other.getClass()) <span class="keyword">return</span> <span class="predefined-constant">false</span>;
      Route route = (Route) other;
      <span class="keyword">if</span> (!origin.equals(route.origin)) <span class="keyword">return</span> <span class="predefined-constant">false</span>;
      <span class="keyword">return</span> destination.equals(route.destination);
    }

    <span class="annotation">@Override</span>
    <span class="directive">public</span> <span class="type">int</span> hashCode() {
      <span class="type">int</span> hashCode = origin.hashCode();
      hashCode = <span class="integer">31</span> * hashCode + destination.hashCode();
      <span class="keyword">return</span> hashCode;
    }
  }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Cache keys needs to define a proper <code>hashCode()</code> and <code>equals()</code> method.</p>
</div>
</div>
<div class="sect2">
<h3 id="keys-need-to-be-immutable"><a class="anchor" href="#keys-need-to-be-immutable"></a>2.7. Keys Need to be Immutable</h3>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="title">Don&#8217;t mutate keys</div>
<div class="paragraph">
<p>For a key instance it is illegal to change its value after it is used for a cache operation.
The cache uses the key instance in its own data structure. When defining your own keys, it is therefore a
good idea to design them as immutable object.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>The above isn&#8217;t special to caching or cache2k, it applies identically when using a Java <code>HashMap</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="mutating-values"><a class="anchor" href="#mutating-values"></a>2.8. Mutating Values</h3>
<div class="paragraph">
<p>It is illegal to mutate a cached value after it was stored in the cache, unless <code>storeByReference</code>
 is enabled. This parameter instructs the cache to keep all cached values inside the heap.</p>
</div>
<div class="paragraph">
<p>Background: cache2k stores its values in the Java heap by the object reference. This means
mutating a value, will affect the cache contents directly. Future versions of cache2k
will have additional storage options and allow cache entries to be migrated to off heap
storage or persisted. In this case mutating cached values directly will lead to inconsistent
results.</p>
</div>
</div>
<div class="sect2">
<h3 id="exceptions-and-caching"><a class="anchor" href="#exceptions-and-caching"></a>2.9. Exceptions and Caching</h3>
<div class="paragraph">
<p>When using read through and a global expiry time (<code>expireAfterWrite</code>) is set, exceptions
will be cached and/or suppressed.</p>
</div>
<div class="paragraph">
<p>A cached exception will be rethrown every time the key is accessed. After some
time passes, the loader will be called again. A cached exception can be spotted by the expiry time
in the exception text, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>org.cache2k.integration.CacheLoaderException: expiry=2016-06-04 06:08:14.967, cause: java.lang.NullPointerException</pre>
</div>
</div>
<div class="paragraph">
<p>Cached exceptions can be misleading, because you may see 100 exceptions in your log, but only
one was generated from the loader. That&#8217;s why the expiry of an exception is typically shorter then
the configured expiry time.</p>
</div>
<div class="paragraph">
<p>When a previous value is available a subsequent loader exception is suppressed for a short time.
For more details on this behavior see the <a href="#resilience">Resilience chapter</a>.</p>
</div>
</div>
<div class="sect2">
<h3 id="don-t-panic"><a class="anchor" href="#don-t-panic"></a>2.10. Don&#8217;t Panic!</h3>
<div class="paragraph">
<p>Also those familiar with caching might get confused by the many parameters and operations of cache2k controlling
nuances of caching semantics. Except for the exceptions caching described above everything will work as you will
expect from a cache. There is no need to know every feature in detail, yet. Think of them as a parachute. Usually you
don&#8217;t need them, but when in trouble, there is one parameter that will save you.</p>
</div>
<div class="paragraph">
<p>Whenever in doubt: For asking questions please use the <em>Stackoverflow</em> tag <code>cache2k</code>. Please describe your scenario
and the problem you try to solve first before asking for specific features of cache2k and how they might
help you.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="types"><a class="anchor" href="#types"></a>3. Types</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This section covers:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>How to construct a cache with concrete types</p>
</li>
<li>
<p>Why you should use types</p>
</li>
<li>
<p>How generic types are captured</p>
</li>
</ul>
</div>
<div class="sect2">
<h3 id="constructing-a-cache-with-generic-types"><a class="anchor" href="#constructing-a-cache-with-generic-types"></a>3.1. Constructing a Cache with Generic Types</h3>
<div class="paragraph">
<p>When using generic types, the cache is constructed the same way as already shown in the
<em>Getting started</em> chapter.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">List</span>&lt;<span class="predefined-type">String</span>&gt;&gt; cache =
      <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">List</span>&lt;<span class="predefined-type">String</span>&gt;&gt;() {}
        .eternal(<span class="predefined-constant">true</span>)
        .build();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>{}</code> is a trick which constructs an anonymous class, which contains the complete type information.
If just an object would be created the complete type information would not be available at runtime and could
not be used for configuring the cache.</p>
</div>
<div class="paragraph">
<p>Caches can be constructed dynamically with arbitrary generic types. The type information can be
specified via the interface <code>CacheType</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="constructing-a-cache-without-generic-types"><a class="anchor" href="#constructing-a-cache-without-generic-types"></a>3.2. Constructing a Cache without Generic Types</h3>
<div class="paragraph">
<p>If the cache types do not contain generic types, then the following simpler builder pattern
can be used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">String</span>&gt; cache =
      Cache2kBuilder.of(<span class="predefined-type">Long</span>.class, <span class="predefined-type">String</span>.class)
        .eternal(<span class="predefined-constant">true</span>)
        .build();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The additional generated class as in the previous version is not needed, which saves a few bytes program code.</p>
</div>
</div>
<div class="sect2">
<h3 id="key-type"><a class="anchor" href="#key-type"></a>3.3. Key Type</h3>
<div class="paragraph">
<p>The key type needs to implement <code>equals()</code> and <code>hashCode()</code>. Arrays are not valid for keys.</p>
</div>
</div>
<div class="sect2">
<h3 id="value-type"><a class="anchor" href="#value-type"></a>3.4. Value Type</h3>
<div class="paragraph">
<p>Using arrays as values is discouraged, because some cache operations testing for value equality,
like <code>Cache.replaceIfEquals()</code>, will not work as desired on arrays.
To prevent problems, cache2k refuses to build a cache with an array value type specified
at the configuration. However, this protection can be circumvented by not providing the
proper type in the cache configuration.</p>
</div>
<div class="paragraph">
<p>If the value type is implementing
<a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/expiry/ValueWithExpiryTime.html"><code>ValueWithExpiryTime</code></a>,
an expiry policy is added automatically.</p>
</div>
</div>
<div class="sect2">
<h3 id="untyped-caches"><a class="anchor" href="#untyped-caches"></a>3.5. Untyped Caches</h3>
<div class="paragraph">
<p>It is possible to construct an untyped cache via <code>Cache2kBuilder.forUnknownTypes()</code>. But, the
use of untyped caches is discouraged. If different types need to be stored in a cache, construct
a separate cache for each type with the proper type information.</p>
</div>
</div>
<div class="sect2">
<h3 id="future-enhancements"><a class="anchor" href="#future-enhancements"></a>3.6. Future Enhancements</h3>
<div class="paragraph">
<p>Future versions of cache2k will leverage the type information for:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>optimizations depending on the type</p>
</li>
<li>
<p>optional strict type checking</p>
</li>
<li>
<p>optional copying</p>
</li>
<li>
<p>derive a optimal marshaller for off heap overflow and persistence</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="atomic-operations"><a class="anchor" href="#atomic-operations"></a>4. Atomic Operations</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Atomic operations allow a combination of read or compare and modify a cached entry
without interference of another thread.</p>
</div>
<div class="sect2">
<h3 id="example"><a class="anchor" href="#example"></a>4.1. Example</h3>
<div class="paragraph">
<p>The method <code>Cache.replaceIfEquals()</code> has the following semantics:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    <span class="keyword">if</span> (cache.containsKey(key) &amp;&amp; Objects.equals(cache.get(key), oldValue)) {
      cache.put(key, newValue);
      <span class="keyword">return</span> <span class="predefined-constant">true</span>;
    } <span class="keyword">else</span>
      <span class="keyword">return</span> <span class="predefined-constant">false</span>;
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>When executing the above statements sequentially, the outcome can vary because other threads can interfere.
The atomic operation semantic guarantees that this is not possible.</p>
</div>
<div class="paragraph">
<p>These kind of operations are also called CAS (compare and swap) operations.</p>
</div>
</div>
<div class="sect2">
<h3 id="built-in-atomic-operations"><a class="anchor" href="#built-in-atomic-operations"></a>4.2. Built-in Atomic Operations</h3>
<div class="paragraph">
<p>In general all operations on a single entry have atomic guarantee. Bulk operations, meaning operations on
multiple keys, like <code>getAll()</code>, don&#8217;t have atomic guarantees.</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Operation</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean containsAndRemove(key)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">remove and return true if something was present</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>V peekAndRemove(key)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">remove and return existing value</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean putIfAbsent(key, value)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">insert value only if no value is present</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>V peekAndReplace(key, value)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Replace value and return old value</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean Cache.replace(key, value)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Replace value and return true when successful</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>V peekAndPut(key, value)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Insert or update value and return the previous value</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean replaceIfEquals(key, expectedValue, newValue)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Replace value only when old value is present in the cache</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>boolean removeIfEquals(key, expectedValue)</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Remove only if present value matches</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="entry-processor"><a class="anchor" href="#entry-processor"></a>4.3. Entry Processor</h3>
<div class="paragraph">
<p>With the entry processor it is possible to implement arbitrary complex operations that are processed atomically
on a cache entry. The interface <code>EntryProcessor</code> must be implemented with the desired semantics and invoked on a cached value
via <code>Cache.invoke()</code>. The bulk operation <code>Cache.invokeAll()</code> is available to process multiple cache entries
with one entry processor.</p>
</div>
<div class="paragraph">
<p>Here is an example which implements the same semantics as <code>replaceIfEquals()</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">      <span class="directive">final</span> K key = ...
      final V oldValue = ...
      final V newValue = ...
      EntryProcessor&lt;K, V, <span class="predefined-type">Boolean</span>&gt; p = <span class="keyword">new</span> EntryProcessor&lt;K, V, <span class="predefined-type">Boolean</span>&gt;() {
        <span class="directive">public</span> <span class="predefined-type">Boolean</span> process(MutableCacheEntry&lt;K, V&gt; entry) {
          <span class="keyword">if</span> (!entry.exists()) {
            <span class="keyword">return</span> <span class="predefined-constant">false</span>;
          }
          <span class="keyword">if</span> (oldValue == <span class="predefined-constant">null</span>) {
            <span class="keyword">if</span> (<span class="predefined-constant">null</span> != entry.getValue()) {
              <span class="keyword">return</span> <span class="predefined-constant">false</span>;
            }
          } <span class="keyword">else</span> {
            <span class="keyword">if</span> (!oldValue.equals(entry.getValue())) {
              <span class="keyword">return</span> <span class="predefined-constant">false</span>;
            }
          }
          entry.setValue(newValue);
          <span class="keyword">return</span> <span class="predefined-constant">true</span>;
        }
      };
      <span class="keyword">return</span> cache.invoke(key, p);
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>Since it is an atomic operation multiple calls on
<a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/processor/MutableCacheEntry.html"><code>MutableCacheEntry</code></a> may have no effect if
neutralising each other. For example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">     entry.setValue(<span class="string"><span class="delimiter">&quot;</span><span class="content">xy</span><span class="delimiter">&quot;</span></span>);
     entry.setValue(<span class="string"><span class="delimiter">&quot;</span><span class="content">abc</span><span class="delimiter">&quot;</span></span>);
     entry.remove();</code></pre>
</div>
</div>
<div class="paragraph">
<p>The effect will be:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>If an entry for the key is existing, the entry will be removed</p>
</li>
<li>
<p>If no entry for the key is existing, the cache state will not change</p>
</li>
<li>
<p>If a cache writer is attached, <code>CacheWriter.delete()</code> will be called in any case</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Via the entry processor, it is also possible to specify an expiry time directly.
Here is an example formulated as Java 8 lambda expression, which inserts a value and
sets the expiry after 120 minutes:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">     cache.invoke(<span class="string"><span class="delimiter">&quot;</span><span class="content">key</span><span class="delimiter">&quot;</span></span>,
       e -&gt; e.setValue(<span class="string"><span class="delimiter">&quot;</span><span class="content">value</span><span class="delimiter">&quot;</span></span>)
             .setExpiry(<span class="predefined-type">System</span>.currentTimeMillis() + <span class="predefined-type">TimeUnit</span>.MINUTES.toMillis(<span class="integer">120</span>)));</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="loading-read-through"><a class="anchor" href="#loading-read-through"></a>5. Loading / Read Through</h2>
<div class="sectionbody">
<div id="loading-read-through" class="paragraph">
<p>In read through operation the cache will fetch the value by itself when the value is retrieved, for
example by <code>Cache.get()</code>. This is also called a <em>loading cache</em> or a <em>self populating cache</em>.</p>
</div>
<div class="sect2">
<h3 id="benefits-of-read-through-operation"><a class="anchor" href="#benefits-of-read-through-operation"></a>5.1. Benefits of Read Through Operation</h3>
<div class="paragraph">
<p>When caching reads, using the cache in read through operation has several advantages:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>No boilerplate code as in cache aside</p>
</li>
<li>
<p>Data source becomes configurable</p>
</li>
<li>
<p>Blocking load operations for identical keys, protection against the cache stampede (See <a href="https://en.wikipedia.org/wiki/Cache_stampede">Wikipedia: Cache Stampede</a>)</p>
</li>
<li>
<p>Automatic refreshing of expired values (refresh ahead)</p>
</li>
<li>
<p>Build-in exception handling like suppression and retries (see <a href="#resilience">Resilience</a> chapter)</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="defining-a-loader"><a class="anchor" href="#defining-a-loader"></a>5.2. Defining a Loader</h3>
<div class="paragraph">
<p>A loader is defined by implementing the abstract class <code>CacheLoader</code>. See the <a href="#getting
started">[getting
started]</a> example about read through.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"> V load(K key) <span class="directive">throws</span> <span class="exception">Exception</span>;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The loader actions may only depend on the input key parameter. In case the load operation
will yield an exception it may be passed on to the cache. How exceptions are handled by the cache
is defined by the resilience policy and explained in the <a href="#resilience">Resilience chapter</a>.</p>
</div>
<div class="paragraph">
<p>The JavaDoc about the <a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/integration/CacheLoader.html"><code>CacheLoader</code></a>
contains additional details.</p>
</div>
</div>
<div class="sect2">
<h3 id="advanced-loader"><a class="anchor" href="#advanced-loader"></a>5.3. Advanced Loader</h3>
<div class="paragraph">
<p>For more sophisticated load operations the <code>AdvancedCacheLoader</code> is available.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java"> V load(K key, <span class="type">long</span> currentTime, CacheEntry&lt;K,V&gt; currentEntry) <span class="directive">throws</span> <span class="exception">Exception</span>;</code></pre>
</div>
</div>
<div class="paragraph">
<p>The information of the current entry can be used to optimize the data request. A typical
example is the optimization of HTTP requests. When the current cached value and its time
is known the request header <code>If-Modified-Since</code> can be set from <code>Entry.getLastModification()</code>.</p>
</div>
<div class="paragraph">
<p>The JavaDoc about the <a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/integration/AdvancedCacheLoader.html"><code>AdvancedCacheLoader</code></a>
contains additional details.</p>
</div>
</div>
<div class="sect2">
<h3 id="using-lambda-loaders-in-java-8"><a class="anchor" href="#using-lambda-loaders-in-java-8"></a>5.4. Using Lambda Loaders in Java 8</h3>
<div class="paragraph">
<p>Instead the abstract loader class, there is also a functional interface available for use with
Java 8.</p>
</div>
</div>
<div class="sect2">
<h3 id="prefetching"><a class="anchor" href="#prefetching"></a>5.5. Prefetching</h3>
<div class="paragraph">
<p>The cache can be instructed to load one or several values in the background with
the <code>prefetch()</code> or <code>prefetchAll()</code> operations. This way data retrieval can be
done in parallel and latencies can be reduced.</p>
</div>
<div class="paragraph">
<p>The number of threads used for prefetching is configured by <code>loaderThreadCount</code>.</p>
</div>
<div class="paragraph">
<p>The operation may have no effect if no loader is defined or if not enough threads
are available.</p>
</div>
</div>
<div class="sect2">
<h3 id="invalidating"><a class="anchor" href="#invalidating"></a>5.6. Invalidating</h3>
<div class="paragraph">
<p>In case the data was updated in the external source, the current cache content
becomes invalid. To notify the cache and eventually update the cached value
several options exist.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>Cache.remove(key)</code></dt>
<dd>
<p>Invalidating an entry with <code>Cache.remove()</code> will cause the entry to be removed from the cache ultimately.
The next time the entry is requested with <code>Cache.get(key)</code> the cache will invoke the loader (if defined).
In case the loader yields an exception, this exception will be propagated to the application since there
is no previous value for fallback. <code>Cache.remove(key)</code> is useful if the data is outdated and old data is
not allowed to be delivered. <code>Cache.remove()</code> will also invoke <code>CacheWriter.delete()</code>, if specified.
Priority is on data consistency.</p>
</dd>
<dt class="hdlist1"><code>Cache.expireAt(key, Expiry.NOW)</code></dt>
<dd>
<p>The entry is expired immediately. If refresh ahead is enabled the loader will be invoked
in the background. Subsequent calls to <code>Cache.get</code> will block until the loading is completed
and return the new value. The operation will have no effect, if there is no cached entry
associated with the key. The value is still available in the cache as fallback if a loader exception occurs.
This variant is the better choice if outdated values are allowed to be visible in the event of
a temporary failure. An inconsistency is only allowed when a temporary failure occurs.</p>
</dd>
<dt class="hdlist1"><code>Cache.expireAt(key, Expiry.REFRESH)</code></dt>
<dd>
<p>When invalidating an entry via <code>Cache.expireAt(key, Expiry.REFRESH)</code> the loader
gets invoked instantly if refresh ahead is enabled. If the loader is invoked, the current value
will stay visible until the updated value is available. If the loader cannot be invoked, the entry is
expired. The operation will have no effect, if there is no cached entry associated with the key. The value
is still available in the cache as fallback if a loader exception occurs. This variant is the better
choice if outdated values are allowed to be visible and the cache should continuously serve data.
Priority is on availability.</p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="transparent-access"><a class="anchor" href="#transparent-access"></a>5.7. Transparent Access</h3>
<div class="paragraph">
<p>When using the cache in read through and/or in write through operation, some methods on the
cache will often be misinterpreted and present pitfalls. For example, the method
<code>Cache.containsKey</code> will not return true when the value exists in the system of authority,
but only reflects the cache state.</p>
</div>
<div class="paragraph">
<p>To prevent pitfalls a reduced set of interfaces is available:
<a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/KeyValueSource.html"><code>KeyValueSource</code></a>,
<a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/AdvancedKeyValueSource.html"><code>AdvancedKeyValueSource</code></a> and
<a href="https://cache2k.org/docs/1.0/apidocs/cache2k-api/index.html?org/cache2k/KeyValueStore.html"><code>KeyValueStore</a></code> are available. These interfaces only contain
methods that act transparently when a loader or writer is defined.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="expiry-and-refresh"><a class="anchor" href="#expiry-and-refresh"></a>6. Expiry and Refresh</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A cached value may expire after some specified time. When expired, the value is not
returned by the cache any more. The cache may be instructed to do an automatic
reload of an expired value, this is called <em>refresh ahead</em>.</p>
</div>
<div class="paragraph">
<p>Expiry does not mean that a cache entry is removed from the cache. The actual
removal from the cache may lag behind the time of expiry.</p>
</div>
<div class="sect2">
<h3 id="specifying-an-expiry-duration"><a class="anchor" href="#specifying-an-expiry-duration"></a>6.1. Specifying an Expiry Duration</h3>
<div class="paragraph">
<p>Expiry after an entry is created or modified can be specified via the <code>expireAfterWrite</code> parameter.
This is also known as <em>time to live</em>. It is possible to specify different expiry values for
created or modification with a custom <code>ExpiryPolicy</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<em>Expiry after access</em> or <em>time to idle</em> is not supported, since it would compromise the high performance
of cache2k. There is seldom a functional requirement for TTI, but it is used
very often to minimize memory consumption in times of low activity. How a similar feature can be
constructed that, at the same time, is not counter productive for performance needs further research.
For discussion, see: <a href="https://github.com/cache2k/cache2k/issues/39">GH 39</a>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="variable-expiry"><a class="anchor" href="#variable-expiry"></a>6.2. Variable Expiry</h3>
<div class="paragraph">
<p>Each entry may have a different expiry time. This can be achieved by specifying an <code>ExpiryPolicy</code>.
The <code>ExpiryPolicy</code> calculates a point in time, when a value expires. The configuration parameter
<code>expireAfterWrite</code> is used as a maximum value.</p>
</div>
</div>
<div class="sect2">
<h3 id="lagging-expiry"><a class="anchor" href="#lagging-expiry"></a>6.3. Lagging Expiry</h3>
<div class="paragraph">
<p>In standard operation time checks when accessing the entry are saved and the actual expiry of an entry
may lag behind, meaning that entries that should expire are visible some milliseconds longer.</p>
</div>
</div>
<div class="sect2">
<h3 id="sharp-expiry"><a class="anchor" href="#sharp-expiry"></a>6.4. Sharp Expiry</h3>
<div class="paragraph">
<p>In case there is a business requirement that data becomes invalid or needs refreshed at a defined point
in time the parameter <code>sharpExpiry</code> can be enabled. This will cause that the expiry happens exactly at
the point in time determined by the expiry policy. For more details see the JavaDoc or
<code>Cache2kBuilder.sharpExpiry</code> and <code>ExpiryPolicy</code>.</p>
</div>
<div class="paragraph">
<p>If <em>sharp expiry and refresh ahead</em> is both enabled, the contract of refresh ahead is relaxed.
The resulting semantics will be:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Entries will expire exactly at the specified time</p>
</li>
<li>
<p>A refresh starts at expiry time</p>
</li>
<li>
<p><code>contains()</code> is <code>false</code>, if the entry is expired and not yet refreshed</p>
</li>
<li>
<p>A <code>get()</code> on the expired entry will stall until refreshed</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Sharp expiry and normal, lagging expiry can be combined. For example, if the parameter <code>expiryAfterWrite</code> and an
<code>ExpiryPolicy</code> is specified and <code>sharpExpiry</code> is enabled. The sharp expiry will be used for the
time calculated by the <code>ExpiryPolicy</code>, but the duration in <code>expireAfterWrite</code> is used if this will be sooner.
If the expiry is result of a duration calculation via <code>expireAfterWrite</code> sharp expiry of the entry will not be
enabled.</p>
</div>
</div>
<div class="sect2">
<h3 id="loader-exceptions-and-expiry"><a class="anchor" href="#loader-exceptions-and-expiry"></a>6.5. Loader Exceptions and Expiry</h3>
<div class="paragraph">
<p>When an expiry duration is specified via <code>expireAfterWrite</code>, resilience features are automatically
active. See the resilience chapter for details.</p>
</div>
</div>
<div class="sect2">
<h3 id="resetting-the-expiry-of-a-cache-value"><a class="anchor" href="#resetting-the-expiry-of-a-cache-value"></a>6.6. Resetting the Expiry of a Cache Value</h3>
<div class="paragraph">
<p>The expiry value can be reset with the method <code>Cache.expireAt(key, time)</code>. Some special values exist:</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<caption class="title">Table 1. <code>Cache.expireAt()</code> constants</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">constant</th>
<th class="tableblock halign-left valign-top">meaning</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Expiry.NOW</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">The value expires immediately. An immediate load is triggered if refreshAhead is enabled.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Expiry.REFRESH</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">An immediate load is triggered if refreshAhead is enabled. If loading is not possible the value expires.</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>Expiry.ETERNAL</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">keep indefinitly or to a maximum of whats set with via <code>expireAfterWrite</code></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>It is possible to atomically examine a cached entry and update its expiry with the <code>EntryProcessor</code> and
<code>MutableCacheEntry.setExpiry()</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="wall-clock-and-clock-skew"><a class="anchor" href="#wall-clock-and-clock-skew"></a>6.7. Wall Clock and Clock Skew</h3>
<div class="paragraph">
<p>For timing reference the Java <code>System.currentTimeMillis()</code> is used. As with any application that relies on
time, it is good practice that the system clock is synchronized with a time reference. When the system time
needs to be corrected, it should adapt slowly to the correct time and keep continuously ascending.</p>
</div>
<div class="paragraph">
<p>In case a clock skew happens regularly a premature or late cache expiry may cause troubles. It is possible
to do some countermeasures. If the time decreases, entries may expire more early. This can be detected and with the
<code>AdvancedCacheLoader</code> the previously loaded value can be reused. If there is a time skew forward, expiry can
be triggered programmatically with <code>expireAt()</code>.</p>
</div>
<div class="paragraph">
<p>Outlook: It is planed for version 1.2 to have a configurable time source, which enables
better adaption to different operating environments. Ideas and requests are welcome.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="refresh-ahead"><a class="anchor" href="#refresh-ahead"></a>7. Refresh Ahead</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With <em>refresh ahead</em> (or <em>background refresh</em>, in a read through configuration,
values about to expire will be refreshed automatically by the cache.</p>
</div>
<div class="sect2">
<h3 id="setup"><a class="anchor" href="#setup"></a>7.1. Setup</h3>
<div class="paragraph">
<p>Refresh ahead can be enabled via <code>refreshAhead</code> switch.
The number of threads used for refreshing is configured by <code>loaderThreadCount()</code>.
A (possibly shared) thread pool for refreshing can be configured via <code>prefetchExecutor()</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="semantics"><a class="anchor" href="#semantics"></a>7.2. Semantics</h3>
<div class="paragraph">
<p>The main purpose of refresh ahead is to ensure that the cache contains fresh data
and that an application never is delayed when data expires and needs a reload.
This leads to several compromises: Expired values will be visible until the new
data is available from the load operation, more then the needed requests will be send
to the loader.</p>
</div>
<div class="paragraph">
<p>After the expiry time of a value is reached, the loader is invoked to fetch a fresh value.
The old value will be returned by the cache, although it is expired, and will be replaced
by the new value, once the loader is finished. When a refresh is needed and not enough loader
threads are available, the value will expire immediately and the next <code>get()</code> request
will trigger the load.</p>
</div>
<div class="paragraph">
<p>Once refreshed, the entry is in a trail period. If it is not accessed until the next
expiry, no refresh will be done, the entry expires and will be removed from the cache.
This means that the time an entry stays within the trail period is determined by the
configured expiry time or the the <code>ExpiryPolicy</code>.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Refresh ahead only works together with the methods invoking the loader, for example
<code>get()</code> and <code>getAll()</code>. After a value is refreshed, an entry will not be visible with
<code>containsKey</code> or <code>peek</code>. The first call to <code>get()</code> or <code>load()</code> on a previously refreshed
item will make the loaded value available in the cache.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="sharp-expiry-vs-refresh-ahead"><a class="anchor" href="#sharp-expiry-vs-refresh-ahead"></a>7.3. Sharp Expiry vs. Refresh Ahead</h3>
<div class="paragraph">
<p>The setting <code>sharpExpiry</code> conflicts with the idea of refresh ahead. When using
refresh ahead and sharp expiry in combination, the value will expire at the specified
time and the background refresh is initiated. When the application requests the value
between the expiry and before the new value is loaded, it blocks until the new value
is available.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Combining sharp expiry, lagging expiry and refresh ahead, leads to an operation mode that
cannot guarantee the sharp expiry contract under all circumstances. If an ongoing load operation
is not finished before a sharp expiry point in time, non fresh data will become visible.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Sharp timeout can also applied on a dynamic per entry basis only when needed.</p>
</div>
</div>
<div class="sect2">
<h3 id="rationale-no-separate-refresh-timing-parameter"><a class="anchor" href="#rationale-no-separate-refresh-timing-parameter"></a>7.4. Rationale: No separate refresh timing parameter?</h3>
<div class="paragraph">
<p>Caches supporting refresh ahead typically have separate configuration parameters for its timing.
In cache2k, refreshing is done when the value would expire, which is controlled by the expiry policy
and <code>expireAfterWrite</code> parameter. Why? It should be possible to enable refresh ahead with a single
switch. Refreshing and expiring are two sides of the same coin: When expired, we need to refresh.</p>
</div>
</div>
<div class="sect2">
<h3 id="future-outlook"><a class="anchor" href="#future-outlook"></a>7.5. Future Outlook</h3>
<div class="paragraph">
<p>More options to control refreshing and the trail period are added in the next releases.</p>
</div>
<div class="paragraph">
<p>The effects on the event listeners and statistics when refreshing may change in the future.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="null-values"><a class="anchor" href="#null-values"></a>8. Null Values</h2>
<div class="sectionbody">
<div class="paragraph">
<p>While a <code>HashMap</code> supports <code>null</code> keys and <code>null</code> values most cache implementations and the JCache standard
do not. By default, cache2k does not permit <code>null</code> values, to avoid surprises, but storing <code>null</code> values
can be allowed with a configuration parameter.</p>
</div>
<div class="sect2">
<h3 id="the-pros-and-cons-of-nulls"><a class="anchor" href="#the-pros-and-cons-of-nulls"></a>8.1. The Pros and Cons of Nulls</h3>
<div class="paragraph">
<p>A good writeup of the topic can be found at
<a href="https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained">Using and Avoiding Null Explained</a>.
The bottom line is, that for a map it is always better to store no mapping instead of a mapping to a <code>null</code> value.
For a cache it is a different story, since the absence of a mapping can mean two things: The data was
not requested from the source yet, or, there is no data.</p>
</div>
</div>
<div class="sect2">
<h3 id="negative-result-caching"><a class="anchor" href="#negative-result-caching"></a>8.2. Negative Result Caching</h3>
<div class="paragraph">
<p>Caching that there is no result or a failure, is also called "negative result caching" or "negative caching".
An example use case is the request of a database entry by primary key, for example via JPA&#8217;s <code>EntityManager.find()</code>
which returns an object if it is available in the database or <code>null</code> if it is not. Caching a negative result
can make sense when requests that generate a negative result are common.</p>
</div>
<div class="paragraph">
<p>In a Java API negative results are quite often modeled with a <code>null</code> value. By enabling <code>null</code> support in
cache2k no further wrapping is required.</p>
</div>
</div>
<div class="sect2">
<h3 id="alternatives"><a class="anchor" href="#alternatives"></a>8.3. Alternatives</h3>
<div class="paragraph">
<p>In a JCache application a <code>null</code> from the <code>CacheLoader</code> means the entry should be removed from the cache.
This semantic is a consistent definition, but if <code>Cache.get()</code> is used to check whether data is
existing, no caching happens if no data is present. A <code>null</code> value is passed through consistently, however,
the cache performs badly if a <code>null</code> response is common.</p>
</div>
<div class="paragraph">
<p>Being able to store a <code>null</code> value is no essential cache feature, since it is always possible
to store a wrapper object in the cache. However, with the <code>null</code> support in cache2k, it is
possible to store a <code>null</code> value with no additional overhead.</p>
</div>
</div>
<div class="sect2">
<h3 id="default-behavior"><a class="anchor" href="#default-behavior"></a>8.4. Default Behavior</h3>
<div class="paragraph">
<p>By default, every attempt to store a <code>null</code> in the cache will yield a <code>NullPointerException</code>.</p>
</div>
<div class="paragraph">
<p>In case <code>peek()</code> returns <code>null</code>, this means there is no associated entry to this
key in the cache. The same holds for <code>get()</code> if no loader is defined. For one point
in time and one key there is the following invariant: <code>cache.contains(key) == (cache.peek(key) != null)</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="how-to-enable-null-values"><a class="anchor" href="#how-to-enable-null-values"></a>8.5. How to Enable Null Values</h3>
<div class="paragraph">
<p>Storing of <code>null</code> values can be enabled by <code>permitNullValues(true)</code>. Example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, Person&gt; cache =
      <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Integer</span>, Person&gt;(){}
        .name(<span class="string"><span class="delimiter">&quot;</span><span class="content">persons</span><span class="delimiter">&quot;</span></span>)
        .entryCapacity(<span class="integer">10000</span>)
        .expireAfterWrite(<span class="integer">5</span>, <span class="predefined-type">TimeUnit</span>.MINUTES)
        .permitNullValues(<span class="predefined-constant">true</span>)
        .build();</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="how-to-operate-with-null-values"><a class="anchor" href="#how-to-operate-with-null-values"></a>8.6. How to Operate with Null Values</h3>
<div class="paragraph">
<p>When <code>null</code> values are legal, additional care must be taken. The typical cache aside pattern becomes invalid:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, Person&gt; c = ...
    Person lookupPerson(<span class="type">int</span> id) {
      Person p = cache.peek(id);
      <span class="keyword">if</span> (p == <span class="predefined-constant">null</span>) {
        p = retrievePerson(id);
        cache.put(id, p);
      }
      <span class="keyword">return</span> p;
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>In case <code>retrievePerson</code> returns <code>null</code> for a non-existing person, it will get called again the next
time the same person is requested. To check whether there is a cached entry <code>containsKey</code> could be used.
However, using <code>containsKey()</code> and <code>get()</code> sequentially is faulty. To check for the existence of a cache
entry and return its value the method <code>peekEntry</code> (or <code>getEntry</code> with loader) can be used.
The fixed version is:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, Person&gt; c = ...
    Person lookupPerson(<span class="type">int</span> id) {
      CacheEntry&lt;Person&gt; e = cache.peekEntry(id);
      <span class="keyword">if</span> (e != <span class="predefined-constant">null</span>) {
        <span class="keyword">return</span> e.getValue();
      }
      p = retrievePerson(id);
      cache.put(id, p);
      <span class="keyword">return</span> p;
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The cache aside pattern serves as a good example here, but is generally not recommended. Better
use read through and define a loader.</p>
</div>
</div>
<div class="sect2">
<h3 id="loader-and-null-values"><a class="anchor" href="#loader-and-null-values"></a>8.7. Loader and Null Values</h3>
<div class="paragraph">
<p>If a loader is defined a call of <code>Cache.get()</code> will either return a non-null value or yield an exception.
If the loader returns <code>null</code>, a <code>NullPointerException</code> is generated and wrapped and propagated via
a <code>CacheLoaderException</code>. This behavior is different from JSR107/JCache which defines that an
entry is removed, when the loader returns <code>null</code>.</p>
</div>
<div class="paragraph">
<p>In case the loader returns <code>null</code> and this should not lead to an exception the following options exist:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Always return a non-null object and include a predicate for the <code>null</code> case, use a list
or Java 8 <code>Optional</code></p>
</li>
<li>
<p>Enable <code>null</code> value support</p>
</li>
<li>
<p>Remove entries from the cache when the loader returns <code>null</code> (as in JCache)</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The expiry policy can be used to remove entries from the cache when the loader returns <code>null</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    ...
    builder.expiryPolicy(<span class="keyword">new</span> ExpiryPolicy&lt;<span class="predefined-type">Integer</span>, Person&gt;() {
      <span class="annotation">@Override</span>
      <span class="directive">public</span> <span class="type">long</span> calculateExpiryTime(K key, V value, <span class="type">long</span> loadTime, CacheEntry&lt;<span class="predefined-type">Integer</span>, Person&gt; oldEntry) {
        <span class="keyword">if</span> (value == <span class="predefined-constant">null</span>) {
          <span class="keyword">return</span> NO_CACHE;
        }
        <span class="keyword">return</span> ETERNAL;
      }
    })
    ...</code></pre>
</div>
</div>
<div class="paragraph">
<p>This works, since the cache checks the <code>null</code> value only after the expiry policy has run and
had decided to store the value.</p>
</div>
</div>
<div class="sect2">
<h3 id="performance"><a class="anchor" href="#performance"></a>8.8. Performance</h3>
<div class="paragraph">
<p>Storing <code>null</code> values has no additional memory or CPU overhead.</p>
</div>
</div>
<div class="sect2">
<h3 id="rationale"><a class="anchor" href="#rationale"></a>8.9. Rationale</h3>
<div class="sect3">
<h4 id="why-support-code-null-code"><a class="anchor" href="#why-support-code-null-code"></a>8.9.1. Why support <code>null</code>?</h4>
<div class="paragraph">
<p>Supporting <code>null</code> needs a more careful design inside the cache and its API. When
this is done, it basically comes for free and makes the cache very effective for use cases
where <code>null</code> values are common.</p>
</div>
</div>
<div class="sect3">
<h4 id="why-is-rejecting-code-null-code-values-the-default"><a class="anchor" href="#why-is-rejecting-code-null-code-values-the-default"></a>8.9.2. Why is rejecting <code>null</code> values the default?</h4>
<div class="paragraph">
<p>We were using cache2k for 16 years, with the capability to store <code>null</code> values by default. For the 1.0 version
we changed this behavior and don&#8217;t allow nulls. Here is why:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Most caches do not support <code>null</code> values. Allowing <code>null</code> by default may lead to unexpected and incompatible behavior.</p>
</li>
<li>
<p>Use cases with <code>null</code> are rare.</p>
</li>
<li>
<p>Returning or storing a <code>null</code> may be a mistake most of the time.</p>
</li>
<li>
<p>In case a <code>null</code> is allowed it is better to specify this explicitly to make the different
behavior more obvious.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="why-rejecting-code-null-code-from-the-loader"><a class="anchor" href="#why-rejecting-code-null-code-from-the-loader"></a>8.9.3. Why rejecting <code>null</code> from the loader?</h4>
<div class="paragraph">
<p>If the loader returns <code>null</code>, a <code>NullPointerException</code> is generated and propagated via
the <code>CacheLoaderException</code>. This behavior is different from JSR107/JCache which defines that an entry
is removed, if the loader returns <code>null</code>.</p>
</div>
<div class="paragraph">
<p>The JCache behavior is consistent, since a <code>get()</code> in JCache returns <code>null</code> only in the case that
no entry is present. The JCache behavior is also useful, since nulls from the loader pass through
transparently. But as soon as nulls are passed through regularly, the cache is rendered useless, since
a <code>null</code> from the loader means "no caching". This will be unnoticed during development but will lead to
performance trouble in production.</p>
</div>
<div class="paragraph">
<p>In cache2k there are different options when <code>null</code> comes into play. A failure
by default will, hopefully, lead to an explicit choice for the best option.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="resilience-and-exceptions"><a class="anchor" href="#resilience-and-exceptions"></a>9. Exceptions and Resilience</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In a read through configuration the cache can tolerate temporary loader failures.
The write through does not provide resilience capabilities at the moment, which means
 a writer exception will always propagated to the cache client.</p>
</div>
<div class="sect2">
<h3 id="behavior"><a class="anchor" href="#behavior"></a>9.1. Behavior</h3>
<div class="paragraph">
<p>The default behavior depends on the general expiry (<code>expiryAfterWrite</code> or <code>eternal</code>) setting of the cache.</p>
</div>
<div class="sect3">
<h4 id="no-expiry"><a class="anchor" href="#no-expiry"></a>9.1.1. No Expiry</h4>
<div class="paragraph">
<p>If no expiry is specified or <code>eternal(true)</code> is specified, all exceptions will be propagated to the client.
The loader will be called immediately again, if the key is requested again.</p>
</div>
</div>
<div class="sect3">
<h4 id="with-expiry"><a class="anchor" href="#with-expiry"></a>9.1.2. With Expiry</h4>
<div class="paragraph">
<p>When an expiry time is specified, the cache also enables the resilience features.</p>
</div>
<div class="paragraph">
<p>If a load yields an exception and there is data in the cache: The exception will not be
propagated to the client, and the cache answers requests with the current cache content.
Subsequent reload attempts that yield an exception, will also be <em>suppressed</em>, if the time span to the
first exception is below the resilience duration setting.</p>
</div>
<div class="paragraph">
<p>If the loader produces subsequent exceptions that is longer then the resilience duration,
the exception will be <em>propagated</em>. The resilience duration can be set with the parameter
<code>resilienceDuration</code>, if not set explicitly it is identical to the <code>expiryAfterWrite</code>
time span.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="retry"><a class="anchor" href="#retry"></a>9.2. Retry</h3>
<div class="paragraph">
<p>After an exception happens the cache will do a retry to load the value again. The retry
is started after the configured retry interval (<code>retryInterval</code>), or, if not
explicitly configured after 5% of the resilience duration. The load is started when the client accesses
the value again, or the cache is doing this by itself if <code>refreshAhead</code> is enabled.</p>
</div>
<div class="paragraph">
<p>To keep the system load in limits in the event of failure, the duration between each retry
increases according to an <em>exponential backoff</em> pattern by the factor of 1.5.
Each duration is further randomized between one half and the full value.
For example, an <code>expireAfterWrite</code> set to 200 seconds will lead to an initial retry
time of 10 seconds. If exceptions persist the retry time will develop as follows:</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<caption class="title">Table 2. Retry intervals with exponential backoff starting at 10 seconds</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">base duration</th>
<th class="tableblock halign-left valign-top">randomized duration range</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">10 seconds</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">5 - 10 seconds</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">15 seconds</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">7.5 - 115 seconds</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">22.5 seconds</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">11.25 - 22.5 seconds</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">33.75 seconds</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">16.875 - 33.75 seconds</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>When reaching the configured expiry the cache will retry at this time interval and
not increase further. The start retry interval and the maximum retry interval can
be specified by <code>retryInterval</code> and <code>maxRetryInterval</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="exception-propagation"><a class="anchor" href="#exception-propagation"></a>9.3. Exception Propagation</h3>
<div class="paragraph">
<p>If an exception cannot be suppressed, it is propagated to the client immediately.
The retry attempts follow the same pattern as above.</p>
</div>
<div class="paragraph">
<p>When propagated, a loader exception is wrapped and rethrown as <code>CacheLoaderException</code>.
A loader exception is potentially rethrown multiple times, if the retry time is not
yet reached. In this situation a rethrown exception contains the text <code>expiry=&lt;timestamp&gt;</code>.
This behavior can be customized by the <code>ExceptionPropagator</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="invalidating-2"><a class="anchor" href="#invalidating-2"></a>9.4. Invalidating</h3>
<div class="paragraph">
<p>An application may need to invalidate a cache entry, so the cache will invoke the loader
again the next time the entry is requested. How the value should be invalidated depends on
the usage scenario and whether availability or consistency has to be priority.</p>
</div>
<div class="paragraph">
<p>To be able to use the resilience features and increase availability in the event of failure
the method <code>expireAt</code> should be preferred for invalidation. See the detailed discussion in the
loading chapter.</p>
</div>
</div>
<div class="sect2">
<h3 id="entry-status-and-code-containskey-code"><a class="anchor" href="#entry-status-and-code-containskey-code"></a>9.5. Entry Status and <code>containsKey</code></h3>
<div class="paragraph">
<p>In case an exception is present, the method <code>containsKey</code> will return <code>true</code>, the methods
<code>putIfAbsent</code> and <code>computeIfAbsent</code> act consequently. This means <code>pufIfAbsent</code> can not be used
to overwrite an entry in exception state with a value.</p>
</div>
<div class="paragraph">
<p>To examine the state of an entry, e.g. whether it contains a value or exception, the method
<code>Cache.peekEntry</code> can be used. To examine the state of an entry and modify it, the entry processor
can be used.</p>
</div>
</div>
<div class="sect2">
<h3 id="configuration-options"><a class="anchor" href="#configuration-options"></a>9.6. Configuration options</h3>
<div class="paragraph">
<p>To customize the behavior the following options exist.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">suppressExceptions</dt>
<dd>
<p>Default is true. If set to false, do not suppress exceptions.</p>
</dd>
<dt class="hdlist1">expireAfterWrite</dt>
<dd>
<p>Time duration after insert or updated an cache entry expires</p>
</dd>
<dt class="hdlist1">resilienceDuration</dt>
<dd>
<p>Time span the cache will suppress loader exceptions if a value is available from
a previous load. Defaults to <code>expiredAfterWrite</code></p>
</dd>
<dt class="hdlist1">mayRetryInterval</dt>
<dd>
<p>The maximum time interval after a retry attempt is made. Defaults to <code>resilienceDuration</code></p>
</dd>
<dt class="hdlist1">retryInterval</dt>
<dd>
<p>Initial time interval after a retry attempt is made. Defaults to 10% of <code>mayRetryInterval</code>, or a minimum of 2 seconds.</p>
</dd>
<dt class="hdlist1">resiliencePolicy</dt>
<dd>
<p>Sets a custom resilience policy to control the cache behavior in the presence of exceptions</p>
</dd>
<dt class="hdlist1">exceptionPropagator</dt>
<dd>
<p>Sets a custom behavior for exception propagation</p>
</dd>
<dt class="hdlist1">refreshAhead</dt>
<dd>
<p>Either the option <code>refreshAhead</code> or <code>keepDataAfterExpired</code> must be enabled to do exception suppression if an expiry is specified</p>
</dd>
<dt class="hdlist1">keepDataAfterExpired</dt>
<dd>
<p>Either the option <code>refreshAhead</code> or <code>keepDataAfterExpired</code> must be enabled to do exception suppression if an expiry is specified</p>
</dd>
</dl>
</div>
</div>
<div class="sect2">
<h3 id="examples"><a class="anchor" href="#examples"></a>9.7. Examples</h3>
<div class="sect3">
<h4 id="no-expiry-2"><a class="anchor" href="#no-expiry-2"></a>9.7.1. No expiry</h4>
<div class="paragraph">
<p>Values do not expire, exceptions are not suppressed. After an exception, the next <code>Cache.get()</code> will trigger
a load.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; c = <span class="keyword">new</span> Cache2kBuilder&lt;&gt;() {}
      .eternal(<span class="predefined-constant">true</span>)
      <span class="comment">/* ... set loader ... */</span>
      .build();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="expire-after-10-minutes"><a class="anchor" href="#expire-after-10-minutes"></a>9.7.2. Expire after 10 minutes</h4>
<div class="paragraph">
<p>Values expire after 10 minutes. Exceptions are suppressed for 10 minutes
as well, if possible. A retry attempt is made after 1 minute. If the cache
continuously receives exceptions for a key, the retry intervals are exponentially
increased up to a maximum interval time of 10 minutes.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; c = <span class="keyword">new</span> Cache2kBuilder&lt;&gt;() {}
      .expireAfterWrite(<span class="integer">10</span>, <span class="predefined-type">TimeUnit</span>.MINUTES)
      .keepDataAfterExpired(<span class="predefined-constant">true</span>)
      <span class="comment">/* ... set loader ... */</span>
      .build();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="reduced-suppression-time"><a class="anchor" href="#reduced-suppression-time"></a>9.7.3. Reduced suppression time</h4>
<div class="paragraph">
<p>Expire entries after 10 minutes. If an exception happens we do not want
the cache to continue to service the previous (and expired) value for too long. In this scenario
it is preferred to propagate an exception rather than serving a potentially outdated value.
On the other side, there may be temporary outages of the network for a maximum of 30 seconds
we like to cover for.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; c = <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt;() {}
      .expireAfterWrite(<span class="integer">10</span>, <span class="predefined-type">TimeUnit</span>.MINUTES)
      .resilienceDuration(<span class="integer">30</span>, <span class="predefined-type">TimeUnit</span>.SECONDS)
      .keepDataAfterExpired(<span class="predefined-constant">true</span>)
      <span class="comment">/* ... set loader ... */</span>
      .build();</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="cached-exceptions"><a class="anchor" href="#cached-exceptions"></a>9.7.4. Cached exceptions</h4>
<div class="paragraph">
<p>No suppression, because values never expire. The only way that a reload can be triggered
is with a reload operation. In this case we do not want suppression, unless
specified explicitly. The loader is not totally reliable, or a smart developer
uses an exception to signal additional information. If exceptions occur, the cache
should not be ineffective and keep exceptions and defer the next retry for 10 seconds.
For requests between the retry interval, the cache will rethrow the previous exception.
The retry interval does not increase, since a maximum timer interval is not specified.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">   Cache&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; c = <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt;() {}
      .eternal(<span class="predefined-constant">true</span>)
      .retryInterval(<span class="integer">10</span>, <span class="predefined-type">TimeUnit</span>.SECONDS)
      <span class="comment">/* ... set loader ... */</span>
      .build();</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="custom-resilience-policy"><a class="anchor" href="#custom-resilience-policy"></a>9.8. Custom resilience policy</h3>
<div class="paragraph">
<p>By registering a custom implementation of the <code>ResiliencePolicy</code> it is possible to
implement a special behavior that is used to determine the cache duration of an
suppressed or cached an exception . Use the existing implementation as an example and starting point.</p>
</div>
</div>
<div class="sect2">
<h3 id="debugging"><a class="anchor" href="#debugging"></a>9.9. Debugging</h3>
<div class="paragraph">
<p>The cache has no support for logging exceptions. If this is needed, it can be achieved
by an adaptor of the <code>CacheLoader</code>.</p>
</div>
<div class="paragraph">
<p>The statistics expose counters for the total number of received load exceptions and the number
of suppressed exception.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="event-listeners"><a class="anchor" href="#event-listeners"></a>10. Event Listeners</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The cache generates events when an entry is inserted or updated.</p>
</div>
<div class="sect2">
<h3 id="listening-to-events"><a class="anchor" href="#listening-to-events"></a>10.1. Listening to Events</h3>
<div class="paragraph">
<p>Event listeners can be added via the cache builder, for example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    Cache2kBuilder.of(<span class="predefined-type">Integer</span>.class, <span class="predefined-type">Integer</span>.class)
      .addListener(<span class="keyword">new</span> CacheEntryCreatedListener&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt;() {
        <span class="annotation">@Override</span>
        <span class="directive">public</span> <span class="type">void</span> onEntryCreated(<span class="directive">final</span> Cache&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; cache,
                                   <span class="directive">final</span> CacheEntry&lt;<span class="predefined-type">Integer</span>, <span class="predefined-type">Integer</span>&gt; entry) {
          <span class="predefined-type">System</span>.err.println(<span class="string"><span class="delimiter">&quot;</span><span class="content">inserted: </span><span class="delimiter">&quot;</span></span> + entry.getKey());
        }
      });</code></pre>
</div>
</div>
<div class="paragraph">
<p>Different listener types are available for insert, update, removal and expiry. The is currently
no possibility to listen to an eviction.</p>
</div>
<div class="paragraph">
<p>Listeners are executed synchronous, meaning the cache operation will not complete until all listeners
are run. The expiry event is always asynchronous.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
It is illegal to mutate cache values inside the listeners.
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="async-listeners"><a class="anchor" href="#async-listeners"></a>10.2. Async Listeners</h3>
<div class="paragraph">
<p>Listeners will be executed asynchronously when added with <code>addAsyncListener()</code>. By default a shared unbounded
executor is used. A custom executor can be set via <code>asyncListenerExecutor</code>.</p>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
The cached value is not copied during the cache operation. If a value instance is mutated after
it was handed over to the cache, asynchronous listeners may not see the value as it was present during
the cache operation.
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="xml-configuration"><a class="anchor" href="#xml-configuration"></a>11. Configuration via XML</h2>
<div class="sectionbody">
<div class="paragraph">
<p>cache2k supports an XML configuration file. The configuration file can contain additional settings that should
not be "buried" inside the applications code.</p>
</div>
<div class="sect2">
<h3 id="using-the-xml-configuration"><a class="anchor" href="#using-the-xml-configuration"></a>11.1. Using the XML Configuration</h3>
<div class="paragraph">
<p>When <code>cache2k-all</code> artifact is used the configuration via XML is included, otherwise the artifact
<code>cache2k-xml-configuration</code> must be added as dependency. In a Java SE environment the default SAX parser
is used. In an Android environment the XML pull parser is used. There are no additional dependencies to
other libraries.</p>
</div>
<div class="paragraph">
<p>If only one cache manager is used, a configuration file can be put at <code>/cache2k.xml</code> in the class path.
Here is an example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml"><span class="tag">&lt;cache2k&gt;</span>
  <span class="comment">&lt;!-- An configuration example for the documentation --&gt;</span>
  <span class="tag">&lt;version&gt;</span>1.0<span class="tag">&lt;/version&gt;</span>
  <span class="tag">&lt;defaultManagerName&gt;</span>default<span class="tag">&lt;/defaultManagerName&gt;</span>
  <span class="tag">&lt;skipCheckOnStartup&gt;</span>true<span class="tag">&lt;/skipCheckOnStartup&gt;</span>
  <span class="tag">&lt;properties&gt;</span>
    <span class="tag">&lt;user&gt;</span>
      <span class="tag">&lt;smallCacheCapacity&gt;</span>12_000<span class="tag">&lt;/smallCacheCapacity&gt;</span>
      <span class="tag">&lt;userHome&gt;</span>${ENV.HOME}<span class="tag">&lt;/userHome&gt;</span>
    <span class="tag">&lt;/user&gt;</span>
  <span class="tag">&lt;/properties&gt;</span>
  <span class="tag">&lt;defaults&gt;</span>
    <span class="tag">&lt;cache&gt;</span>
      <span class="tag">&lt;entryCapacity&gt;</span>100_000<span class="tag">&lt;/entryCapacity&gt;</span>
    <span class="tag">&lt;/cache&gt;</span>
  <span class="tag">&lt;/defaults&gt;</span>
  <span class="tag">&lt;templates&gt;</span>
    <span class="tag">&lt;cache&gt;</span>
      <span class="tag">&lt;name&gt;</span>regularExpiry<span class="tag">&lt;/name&gt;</span>
      <span class="tag">&lt;expireAfterWrite&gt;</span>5m<span class="tag">&lt;/expireAfterWrite&gt;</span>
    <span class="tag">&lt;/cache&gt;</span>
    <span class="tag">&lt;cache&gt;</span>
      <span class="tag">&lt;name&gt;</span>lessResilient<span class="tag">&lt;/name&gt;</span>
      <span class="tag">&lt;resilienceDuration&gt;</span>1m<span class="tag">&lt;/resilienceDuration&gt;</span>
    <span class="tag">&lt;/cache&gt;</span>
  <span class="tag">&lt;/templates&gt;</span>
  <span class="tag">&lt;caches&gt;</span>
    <span class="tag">&lt;cache&gt;</span>
      <span class="tag">&lt;name&gt;</span>users<span class="tag">&lt;/name&gt;</span>
      <span class="tag">&lt;entryCapacity&gt;</span>${TOP.properties.user.smallCacheCapacity}<span class="tag">&lt;/entryCapacity&gt;</span>
      <span class="tag">&lt;loader&gt;</span>
        <span class="tag">&lt;byClassName&gt;</span>
          <span class="tag">&lt;className&gt;</span>org.example.MyLoader<span class="tag">&lt;/className&gt;</span>
        <span class="tag">&lt;/byClassName&gt;</span>
      <span class="tag">&lt;/loader&gt;</span>
    <span class="tag">&lt;/cache&gt;</span>
    <span class="tag">&lt;cache&gt;</span>
      <span class="tag">&lt;name&gt;</span>products<span class="tag">&lt;/name&gt;</span>
      <span class="tag">&lt;include&gt;</span>regularExpiry,lessResilient<span class="tag">&lt;/include&gt;</span>
    <span class="tag">&lt;/cache&gt;</span>
  <span class="tag">&lt;/caches&gt;</span>
<span class="tag">&lt;/cache2k&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="combine-programmatic-and-xml-configuration"><a class="anchor" href="#combine-programmatic-and-xml-configuration"></a>11.2. Combine Programmatic and XML Configuration</h3>
<div class="paragraph">
<p>The XML configuration can provide a default setup and a specific setup for a named cache.
The specific setup from the XML configuration is applied after setup from the builder, thus
overwriting any defaults or settings via the builder from the program code.</p>
</div>
<div class="paragraph">
<p>When a cache is created via the builder it needs to have mandatory properties on
the programmatic level:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Type for key and value</p>
</li>
<li>
<p>Cache name</p>
</li>
<li>
<p>Manager with classloader, if another manager or classloader should be used</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>It is recommended to do settings in the builder, that belong to the application code, for example:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1"><code>eternal(true)</code></dt>
<dd>
<p>if no expiry is needed, in case the values are immutable or never change</p>
</dd>
<dt class="hdlist1"><code>eternal(false)</code></dt>
<dd>
<p>if entries need to expire, but no specific time is set on programmatic level</p>
</dd>
<dt class="hdlist1"><code>permitNullValues(true)</code></dt>
<dd>
<p>if the application needs to store <code>nulls</code> in the cache</p>
</dd>
<dt class="hdlist1"><code>storeByReference(true)</code></dt>
<dd>
<p>if the application relies on the fact that the objects are only
stored in the heap and not copied.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>For example, the cache is created in the code with:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="Java">    Cache&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt; b =
      <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">String</span>, <span class="predefined-type">String</span>&gt;(){}
        .name(<span class="string"><span class="delimiter">&quot;</span><span class="content">various</span><span class="delimiter">&quot;</span></span>)
        .eternal(<span class="predefined-constant">true</span>)
        .permitNullValues(<span class="predefined-constant">true</span>)
        .build();</code></pre>
</div>
</div>
<div class="paragraph">
<p>In the configuration file only the capacity is altered:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="Java">  &lt;cache&gt;
    &lt;name&gt;various&lt;/name&gt;
    &lt;entryCapacity&gt;<span class="integer">10</span>K&lt;/entryCapacity&gt;
  &lt;/cache&gt;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="reference-documentation"><a class="anchor" href="#reference-documentation"></a>11.3. Reference Documentation</h3>
<div class="sect3">
<h4 id="file-location"><a class="anchor" href="#file-location"></a>11.3.1. File Location</h4>
<div class="paragraph">
<p>The configuration for the default cache manager (<code>CacheManager.getInstance()</code>) is expected in the class path at
<code>/cache2k.xml</code>. If a different class loader is used to create the cache manager, that is used to look up the configuration.
If multiple cache managers are used, each cache manager can have its own configuration, which is looked after at
<code>/cache2k-${managerName}.xml</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="options"><a class="anchor" href="#options"></a>11.3.2. Options</h4>
<div class="paragraph">
<p>Some options control how the configuration is interpreted.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">version</dt>
<dd>
<p>Version which controls how the configuration is interpreted. Needed for possible
future changes. Always <code>1.0</code> at the moment.</p>
</dd>
<dt class="hdlist1">defaultManagerName</dt>
<dd>
<p>Set another name for the default cache manager, default is <code>"default"</code>.</p>
</dd>
<dt class="hdlist1">ignoreAnonymousCache</dt>
<dd>
<p>If <code>true</code>, allows cache without name. If a cache has no name
a special configuration cannot be applied. The default is <code>false</code>,
enforcing that all caches are named on the programmatic level.</p>
</dd>
<dt class="hdlist1">skipCheckOnStartup</dt>
<dd>
<p>Do not check whether all cache configurations can be applied
properly at startup. Default is <code>false</code>.</p>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="default-configuration"><a class="anchor" href="#default-configuration"></a>11.3.3. Default Configuration</h4>
<div class="paragraph">
<p>A default configuration may be provided in <code>defaults.cache</code> (see example above). The defaults will be used
for every cache created in the cache manager.</p>
</div>
</div>
<div class="sect3">
<h4 id="templates"><a class="anchor" href="#templates"></a>11.3.4. Templates</h4>
<div class="paragraph">
<p>Multiple template configurations can be provided under <code>templates</code>. Templates have a name.
In the cache configuration, a template can be included via <code>include</code>. Multiple templates can be included
when separated with comma.</p>
</div>
<div class="paragraph">
<p>Templates can be used for other configuration sections as well.</p>
</div>
</div>
<div class="sect3">
<h4 id="parameters"><a class="anchor" href="#parameters"></a>11.3.5. Parameters</h4>
<div class="paragraph">
<p>The values may contain the parameters in the the style <code>${scope.name}</code>. A parameter name starts with a scope.
Predefined scopes are:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">ENV</dt>
<dd>
<p>environment variable, e.g. <code>${ENV.HOME}</code> is the user home directory.</p>
</dd>
<dt class="hdlist1">TOP</dt>
<dd>
<p>references the configuration root, e.g. <code>${TOP.caches.flights.entryCapacity}</code> references the value of the
<code>entryCapacity</code> of the cache named <code>flights</code>.</p>
</dd>
<dt class="hdlist1">PROP</dt>
<dd>
<p>a Java system property, e.g. <code>${PROP.java.home}</code> for the JDK installation directory.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The scope prefix can also reference a parent element name. If the scope prefix is empty an value at the same level
is referenced.</p>
</div>
<div class="paragraph">
<p>A configuration can contain user defined properties in the <code>properties.user</code> section.</p>
</div>
</div>
<div class="sect3">
<h4 id="primitive-types"><a class="anchor" href="#primitive-types"></a>11.3.6. Primitive Types</h4>
<div class="paragraph">
<p>The configuration supports basic types.</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<caption class="title">Table 3. Supported Types in XML Configuration</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
<col style="width: 33.3334%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">type</th>
<th class="tableblock halign-left valign-top">example</th>
<th class="tableblock halign-left valign-top">description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>true</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Boolean value either true of false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">int</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>4711</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Integer value</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">long</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>20_000MiB</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Long value with optional suffixes (see below)</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">String</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>alice</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">A string value</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>For additional convenience the long type supports a unit suffix:</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">suffix</th>
<th class="tableblock halign-left valign-top">value</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">KiB</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1024</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">MiB</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1024^2</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">GiB</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1024^3</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">TiB</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1024^4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">k</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">M</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000^2</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">G</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000^3</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">T</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000^4</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">s</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">m</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000*60</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">h</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000*60*60</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">d</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">1000*60*60*24</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>A long value may also contain the character '_' for structuring. This character is ignored. Example: <code>12_000_000</code>.
The unit suffix is intended to make the configuration more readable. There is no enforcement that a unit actually
matches with the intended unit of the configuration value.</p>
</div>
</div>
<div class="sect3">
<h4 id="sections"><a class="anchor" href="#sections"></a>11.3.7. Sections</h4>
<div class="paragraph">
<p>The cache configuration may contain additional sections. At the moment only the section <code>jcache</code> is available
which tweaks JCache semantics.</p>
</div>
</div>
<div class="sect3">
<h4 id="customizations"><a class="anchor" href="#customizations"></a>11.3.8. Customizations</h4>
<div class="paragraph">
<p>Customizations, for example, loaders, expiry policy and listeners, may be configured. The simplest
method is to specify a class name of the customization that gets created when the cache is build (see also example above).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="XML">  <span class="tag">&lt;loader&gt;</span>
    <span class="tag">&lt;byClassName&gt;</span>
      <span class="tag">&lt;className&gt;</span>org.example.MyLoader<span class="tag">&lt;/className&gt;</span>
    <span class="tag">&lt;/byClassName&gt;</span>
  <span class="tag">&lt;/loader&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>I is also possible to implement an own <code>CustomizationSupplier</code> which can take additional parameters for additional
configuration of the customization. In this case the <code>type</code> element is used to specify the supplier class.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="XML">  <span class="tag">&lt;loader&gt;</span>
    <span class="tag">&lt;bean&gt;</span>
      <span class="tag">&lt;type&gt;</span>org.exmample.LoaderSupplier<span class="tag">&lt;/type&gt;</span>
      <span class="comment">&lt;!-- Additional bean properties to set on the supplier follow. --&gt;</span>
      <span class="tag">&lt;database&gt;</span>jdbc://....<span class="tag">&lt;/database&gt;</span>
    <span class="tag">&lt;/bean&gt;</span>
  <span class="tag">&lt;/loader&gt;</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="rationale-2"><a class="anchor" href="#rationale-2"></a>11.4. Rationale</h3>
<div class="paragraph">
<p>Most of the configuration processing is not limited to XML. The general structure of the configuration can
be represented in YAML or JSON as well. This is why we do not use any XML attributes. Readers for
other formats can implement the <code>ConfigurationTokenizer</code>.</p>
</div>
<div class="paragraph">
<p>The configuration code is mostly generic and uses reflection. In case new properties or configuration classes
are added, there is no need to update configuration code. This way the extra code for the XML configuration keeps
small. Eventually we will separate the configuration into another project so is can be used by other applications or
libraries with their configuration beans.</p>
</div>
<div class="paragraph">
<p>The structure adheres to a strict scheme of <code>container.type.property.type.properties [ .type.property &#8230;&#8203;]</code>.
This simplifies the processing and also leaves room for extensions.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="logging"><a class="anchor" href="#logging"></a>12. Logging</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The log output of cache2k is very sparse, however, some critical information could be send to the
log, so proper logging configuration is essential.</p>
</div>
<div class="sect2">
<h3 id="supported-log-infrastructure"><a class="anchor" href="#supported-log-infrastructure"></a>12.1. Supported Log Infrastructure</h3>
<div class="paragraph">
<p>cache2k supports different logging facades and the JDK standard logging. The supported mechanisms
include:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>SLF4J</p>
</li>
<li>
<p>Apache Commons Logging</p>
</li>
<li>
<p>JDK standard logging</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The availability is evaluated in the above order and the first match is picked and used exclusively for
log output. E.g. if the slf4j-api is present, the log output will be directed to SLF4J. This scheme should have
the desired results, without the need of additional configuration of the used logging facade.</p>
</div>
</div>
<div class="sect2">
<h3 id="wiring-a-custom-log-target"><a class="anchor" href="#wiring-a-custom-log-target"></a>12.2. Wiring a Custom Log Target</h3>
<div class="paragraph">
<p>In case none of the above logging infrastructure can be used the service provider interface
<code>org.cache2k.core.util.LogFactory</code> can be implemented and provided via the <code>ServiceLoader</code> mechanism.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="statistics"><a class="anchor" href="#statistics"></a>13. Statistics</h2>
<div class="sectionbody">
<div class="paragraph">
<p>cache2k collects statistics by default and exposes them via JMX.</p>
</div>
<div class="sect2">
<h3 id="jmx-metrics"><a class="anchor" href="#jmx-metrics"></a>13.1. JMX Metrics</h3>
<div class="paragraph">
<p>When using the <code>cache2k-all</code> artifact for runtime, JMX support ist available. Otherwise the additional
<code>cache2k-server-side</code> artifact needs to be added as dependency.</p>
</div>
<div class="paragraph">
<p>The management beans are registered with the platform MBean server. The object name of a cache follows the
pattern <code>org.cache2k:type=Cache,manager=&lt;managerName&gt;,name=&lt;cacheName&gt;</code>, the object name of a cache manager
follows the pattern <code>org.cache2k:type=CacheManager,name=&lt;managerName&gt;</code>.</p>
</div>
<div class="paragraph">
<p>More detailed information can be found in the API documentation:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://cache2k.org/docs/1.0/apidocs/cache2k-jmx-api/index.html?org/cache2k/jmx/CacheInfoMXBean.html">MXBean for the cache</a></p>
</li>
<li>
<p><a href="https://cache2k.org/docs/1.0/apidocs/cache2k-jmx-api/index.html?org/cache2k/jmx/CacheManagerInfoMXBean.html">MXBean for the cache manager</a></p>
</li>
</ul>
</div>
<div class="sect3">
<h4 id="conflicting-manager-names-in-jmx"><a class="anchor" href="#conflicting-manager-names-in-jmx"></a>13.1.1. Conflicting Manager Names in JMX</h4>
<div class="paragraph">
<p>Multiple cache managers with the identical name may coexist under different class loaders. With JMX enabled, this
will lead to identical JMX objects and refusal of operation. A workaround is to use unique cache manager names.
The name of the default manager, which is usually <code>"default"</code> can be changed via the XML configuration, JNDI or
a call to <code>CacheManager.setDefaultName</code> early in the application startup.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="code-tostring-code-output"><a class="anchor" href="#code-tostring-code-output"></a>13.2. <code>toString()</code> Output</h3>
<div class="paragraph">
<p>The output of the <code>toString()</code> method is extensive and also includes internal statistics. Example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>Cache{database}(size=50003, capacity=50000, get=102876307, miss=1513517, put=0, load=4388352, reload=0, heapHit=101362790, refresh=2874835, refreshFailed=42166, refreshedHit=2102885, loadException=0, suppressedException=0, new=1513517, expire=587294, remove=8156, clear=0, removeByClear=0, evict=868064, timer=3462129, goneSpin=0, hitRate=98.52%, msecs/load=0.425, asyncLoadsStarted=2874835, asyncLoadsInFlight=0, loaderThreadsLimit=8, loaderThreadsMaxActive=8, created=2016-12-02 03:41:34.367, cleared=-, infoCreated=2016-12-02 14:34:34.503, infoCreationDeltaMs=21, collisions=8288, collisionSlots=7355, longestSlot=5, hashQuality=83, noCollisionPercent=83, impl=HeapCache, eviction0(impl=ClockProPlusEviction, chunkSize=11, coldSize=749, hotSize=24252, hotMaxSize=24250, ghostSize=12501, coldHits=11357227, hotHits=38721511, ghostHits=294065, coldRunCnt=444807, coldScanCnt=698524, hotRunCnt=370773, hotScanCnt=2820434), eviction1(impl=ClockProPlusEviction, chunkSize=11, coldSize=778, hotSize=24224, hotMaxSize=24250, ghostSize=12501, coldHits=11775594, hotHits=39508458, ghostHits=283324, coldRunCnt=423258, coldScanCnt=674762, hotRunCnt=357457, hotScanCnt=2689129), evictionRunning=0, keyMutation=0, internalException=0, integrityState=0.17.a6c585b1)</pre>
</div>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>Do to the internal organization of the internal data structures retrieving statistics is a very costly
operation, since it involves scanning through the cache content.</p>
</div>
</td>
</tr>
</table>
</div>
<div class="admonitionblock warning">
<table>
<tr>
<td class="icon">
<i class="fa icon-warning" title="Warning"></i>
</td>
<td class="content">
<div class="paragraph">
<p>The output of <code>toString()</code> may change between releases. It should give valuable information for debugging,
but it shouldn&#8217;t be consumed by application logic.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
<div class="sect2">
<h3 id="accuracy-overhead-and-performance"><a class="anchor" href="#accuracy-overhead-and-performance"></a>13.3. Accuracy, Overhead and Performance</h3>
<div class="paragraph">
<p>The statistics gathering has a very low operational overhead and is enabled by default. Obtaining the statistics
is a costly operation, since the cache needs to aggregate counters of all cache entries.</p>
</div>
<div class="paragraph">
<p>Since high poll frequencies on the statistic values may produce a high system load, the cache has
countermeasures and only aggregates new data after some time has passed. The <code>toString</code> output and the JMX bean
contains the timestamp <code>infoCreated</code> and the value <code>infoCreationDeltaMs</code> to get more insight in this behavior.</p>
</div>
<div class="paragraph">
<p>The switch <code>disableStatistics</code> disables some statistic values that have a significant overhead, for example the
counter for misses or updates.</p>
</div>
<div class="paragraph">
<p>The metric <code>getCount</code> is not totally accurate and may count fewer accesses depending on the amount of concurrency.
The implementation uses a dirty counter per cache entry. The counter is used for the eviction as well, thus the
access statistics are a by-product. The error is relatively small. Future releases may contain the option to
obtain precise statistics.</p>
</div>
</div>
<div class="sect2">
<h3 id="internal-statistics"><a class="anchor" href="#internal-statistics"></a>13.4. Internal Statistics</h3>
<div class="paragraph">
<p>The cache implementation has a lot statistics counters, that are exposed in an internal interface. This
can be revealed via <code>((InternalCache) cache).getInfo()</code> and needs the <code>cache2k-core</code> artifact in the
compile scope. However, internal interfaces may change from release to release.</p>
</div>
</div>
<div class="sect2">
<h3 id="noteworthy-metrics"><a class="anchor" href="#noteworthy-metrics"></a>13.5. Noteworthy Metrics</h3>
<div class="paragraph">
<p>Some special metrics need some more explanation.</p>
</div>
<div class="sect3">
<h4 id="hash-quality"><a class="anchor" href="#hash-quality"></a>13.5.1. Hash Quality</h4>
<div class="paragraph">
<p>Value between 100 and 0 to help evaluate the quality of the hashing function.
100 means perfect. This metric takes into account the collision to size ratio, the longest collision size
and the collision to slot ratio. The value reads 0 if the longest collision size gets more
then 20.</p>
</div>
<div class="paragraph">
<p>The number of collisions and the longest size of a collision slot is also available via JMX.</p>
</div>
</div>
<div class="sect3">
<h4 id="key-mutation-counter"><a class="anchor" href="#key-mutation-counter"></a>13.5.2. Key Mutation Counter</h4>
<div class="paragraph">
<p>Storing objects by reference means it is possible for the application to alter the object
value after it was involved in a cache operation. In case of the key object, this means that the
internal data structure of the cache will be invalid after an illegal mutation.</p>
</div>
<div class="paragraph">
<p>Within the cache eviction a key mutation is detected. The counter is incremented and a warning
is written to the log. Per cache the warning is only logged once.</p>
</div>
<div class="paragraph">
<p>Whenever <code>keyMutationCount</code> is non-zero, check and correct your application.</p>
</div>
</div>
<div class="sect3">
<h4 id="alert"><a class="anchor" href="#alert"></a>13.5.3. Alert</h4>
<div class="paragraph">
<p>The cache as well as the cache manager have a single value health status which is intended for
systems monitoring. The value 0 means everything is okay, 1 means warning, 2 means failure.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="android"><a class="anchor" href="#android"></a>14. Android</h2>
<div class="sectionbody">
<div class="paragraph">
<p>cache2k is compatible with Java 6 and Android. Regular testing is done against API level 16.</p>
</div>
<div class="sect2">
<h3 id="usage"><a class="anchor" href="#usage"></a>14.1. Usage</h3>
<div class="paragraph">
<p>Include the following dependencies:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-api<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span>
    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-core<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
      <span class="tag">&lt;scope&gt;</span>runtime<span class="tag">&lt;/scope&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="xml-configuration-2"><a class="anchor" href="#xml-configuration-2"></a>14.2. XML Configuration</h3>
<div class="paragraph">
<p>The XML configuration is usable for Android. The additional library needs to be included:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-xml-configuration<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
      <span class="tag">&lt;scope&gt;</span>runtime<span class="tag">&lt;/scope&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="jcache"><a class="anchor" href="#jcache"></a>15. JCache</h2>
<div class="sectionbody">
<div class="paragraph">
<p>cache2k supports the JCache API standard. The implementation is compatible to the JSR107 TCK.</p>
</div>
<div class="sect2">
<h3 id="maven-dependencies"><a class="anchor" href="#maven-dependencies"></a>15.1. Maven Dependencies</h3>
<div class="paragraph">
<p>Additionally to the normal cache2k dependencies the following dependencies need to be added:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-all<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
      <span class="tag">&lt;scope&gt;</span>runtime<span class="tag">&lt;/scope&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span>
    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-jcache<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
      <span class="tag">&lt;scope&gt;</span>runtime<span class="tag">&lt;/scope&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span>
    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>javax.cache<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache-api<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>1.1.0<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="getting-started-with-the-jcache-api"><a class="anchor" href="#getting-started-with-the-jcache-api"></a>15.2. Getting Started with the JCache API</h3>
<div class="paragraph">
<p>Since cache2k is JCache compatible, any available JCache introduction can be used for the
first steps. The following online sources are recommended:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://dzone.com/refcardz/java-caching" class="bare">https://dzone.com/refcardz/java-caching</a></p>
</li>
<li>
<p><a href="https://www.youtube.com/watch?v=EugtmOaZn9w" class="bare">https://www.youtube.com/watch?v=EugtmOaZn9w</a></p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="configuration"><a class="anchor" href="#configuration"></a>15.3. Configuration</h3>
<div class="paragraph">
<p>JCache does not define a complete cache configuration, for example, configuring the
cache capacity is not possible. To specify a meaningful cache configuration, the cache2k configuration mechanism
needs to be utilized.</p>
</div>
<div class="sect3">
<h4 id="programmatic-configuration"><a class="anchor" href="#programmatic-configuration"></a>15.3.1. Programmatic Configuration</h4>
<div class="paragraph">
<p>To create a JCache with an additional cache2k configuration the interface <code>ExtendedConfiguration</code>
and the class <code>MutableExtendedConfiguration</code> is provided. The configuration classes are available in
separate API packages, that need to be included in the compile scope:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="xml">    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-api<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
      <span class="tag">&lt;scope&gt;</span>provided<span class="tag">&lt;/scope&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span>
    <span class="tag">&lt;dependency&gt;</span>
      <span class="tag">&lt;groupId&gt;</span>org.cache2k<span class="tag">&lt;/groupId&gt;</span>
      <span class="tag">&lt;artifactId&gt;</span>cache2k-jcache-api<span class="tag">&lt;/artifactId&gt;</span>
      <span class="tag">&lt;version&gt;</span>${cache2k-version}<span class="tag">&lt;/version&gt;</span>
    <span class="tag">&lt;/dependency&gt;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Example usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    CachingProvider p = Caching.getCachingProvider();
    CacheManager cm = p.getCacheManager();
    Cache&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">Double</span>&gt; cache = cm.createCache(<span class="string"><span class="delimiter">&quot;</span><span class="content">aCache</span><span class="delimiter">&quot;</span></span>, ExtendedMutableConfiguration.of(
      <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">Double</span>&gt;(){}
        .entryCapacity(<span class="integer">10000</span>)
        .expireAfterWrite(<span class="integer">5</span>, <span class="predefined-type">TimeUnit</span>.MINUTES)
    ));</code></pre>
</div>
</div>
<div class="paragraph">
<p>When a cache2k configuration is provided, the default behavior is not 100% JCache compatible any more, because
the defaults of cache2k apply. Strict JCache behavior can be enabled again, if needed. The areas of difference
are explained below:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Expiry</dt>
<dd>
<p>With pure JCache configuration the expiry is set to sharp expiry by default for maximum compatiblity. When the
cache2k configuration is used, sharp expiry is off and need to be enabled explicitly.</p>
</dd>
<dt class="hdlist1"><code>Configuration.isStoreByValue</code></dt>
<dd>
<p>When the cache2k configuration is active the parameter will be ignored, if true.
Store by value semantics can enabled again in the JCache configuration section of cache2k
<code>JCacheConfiguration.Builder.copyAlwaysIfRequested</code>. See example below how to specify the additional parameters.</p>
</dd>
</dl>
</div>
<div class="paragraph">
<p>The JCache configuration and the cache2k configuration may have settings that control the same
feature, for example expiry. In this case the two configurations need to be merged and conflicting settings
have to be resolved. The policy is as follows:</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Expiry settings</dt>
<dd>
<p>Settings in cache2k configuration take precedence. A configured expiry policy in the standard
JCache <code>CacheConfiguration</code> will be ignored if either <code>expiryAfterWrite</code> or <code>expiryPolicy</code> is specified in
the cache2k configuration.</p>
</dd>
<dt class="hdlist1">Loader and Writer</dt>
<dd>
<p>Settings in JCache configuration take precedence. If a loader or a writer is specified in the
JCache <code>CacheConfiguration</code> the setting in the cache2k configuration is ignored.</p>
</dd>
<dt class="hdlist1">Event listeners</dt>
<dd>
<p>Registered listeners of both configurations will be used.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect2">
<h3 id="control-additional-jcache-semantics"><a class="anchor" href="#control-additional-jcache-semantics"></a>15.4. Control Additional JCache Semantics</h3>
<div class="paragraph">
<p>The JCache implementation has additional options that control its semantics. These options are available in
the <code>JCacheConfiguration</code> configuration section, which is provided by the <code>cache2k-jcache-api</code> module.</p>
</div>
<div class="paragraph">
<p>Example usage:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="CodeRay highlight"><code data-lang="java">    CachingProvider p = Caching.getCachingProvider();
    CacheManager cm = p.getCacheManager();
    Cache&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">Double</span>&gt; cache = cm.createCache(<span class="string"><span class="delimiter">&quot;</span><span class="content">aCache</span><span class="delimiter">&quot;</span></span>, ExtendedMutableConfiguration.of(
      <span class="keyword">new</span> Cache2kBuilder&lt;<span class="predefined-type">Long</span>, <span class="predefined-type">Double</span>&gt;(){}
        .entryCapacity(<span class="integer">10000</span>)
        .expireAfterWrite(<span class="integer">5</span>, <span class="predefined-type">TimeUnit</span>.MINUTES)
        .with(<span class="keyword">new</span> JCacheConfiguration.Builder()
          .copyAlwaysIfRequested(<span class="predefined-constant">true</span>)
        )
    ));</code></pre>
</div>
</div>
<div class="paragraph">
<p>The example enables store by value semantics again and requests that keys and values are copied when passed
to the cache or retrieved from the cache.</p>
</div>
</div>
<div class="sect2">
<h3 id="implementation-details"><a class="anchor" href="#implementation-details"></a>15.5. Implementation Details</h3>
<div class="sect3">
<h4 id="semantic-changes-since-jcache-1-0"><a class="anchor" href="#semantic-changes-since-jcache-1-0"></a>15.5.1. Semantic Changes Since JCache 1.0</h4>
<div class="paragraph">
<p>The JCache specification team has made some changes to its TCK since the original 1.0 release.
The cache2k implementation already adheres to the latest corrected TCK 1.1.</p>
</div>
<table class="tableblock frame-all grid-all" style="width: 70%;">
<caption class="title">Table 4. Corrected or Enforced JSR107 Semantics in TCK 1.1</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Affected Component</th>
<th class="tableblock halign-left valign-top">JSR107 GitHub issue</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>EntryProcessorException</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107tck/issues/85" class="bare">https://github.com/jsr107/jsr107tck/issues/85</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Customizations may implement <code>Closeable</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107tck/issues/100" class="bare">https://github.com/jsr107/jsr107tck/issues/100</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CacheEntry.getOldValue()</code> for removed event</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107spec/issues/391" class="bare">https://github.com/jsr107/jsr107spec/issues/391</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Statistics of <code>Cache.putIfAbsent()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107tck/issues/63" class="bare">https://github.com/jsr107/jsr107tck/issues/63</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CacheManager.getCacheNames()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107tck/issues/87" class="bare">https://github.com/jsr107/jsr107tck/issues/87</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>CacheManager.getCache()</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107spec/issues/340" class="bare">https://github.com/jsr107/jsr107spec/issues/340</a></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">JMX statistics</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="https://github.com/jsr107/jsr107tck/issues/83" class="bare">https://github.com/jsr107/jsr107tck/issues/83</a></p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="expiry-policy"><a class="anchor" href="#expiry-policy"></a>15.5.2. Expiry Policy</h4>
<div class="paragraph">
<p>If configured via cache2k mechanisms, the cache2k expiry settings take precedence.</p>
</div>
<div class="paragraph">
<p>If a JCache configuration is present for the expiry policy the policies <code>EternalExpiryPolicy</code>,
<code>ModifiedExpiredPolicy</code> and <code>CreatedExpiredPolicy</code> will be handled efficiently. A custom
implementation of the <code>ExpiryPolicy</code> will induce additional operational overhead.</p>
</div>
<div class="paragraph">
<p>The use of <code>TouchedExpiryPolicy</code> or <code>ExpiryPolicy.getExpiryAccess()</code> is discouraged. Test performance
carefully before use in production.</p>
</div>
</div>
<div class="sect3">
<h4 id="store-by-value"><a class="anchor" href="#store-by-value"></a>15.5.3. Store by Value</h4>
<div class="paragraph">
<p>If configured via cache2k mechanisms, store by value semantics are not provided by cache2k by default.
Instead the usual in process semantics are provided. Applications should not rely on the fact
that values or keys are copied by the cache in general.</p>
</div>
<div class="paragraph">
<p>For heap protection cache2k is able to copy keys and values. This can be enabled via the parameter
<code>JCacheConfiguration.setCopyAlwaysIfRequested</code>, see the configuration example above.</p>
</div>
</div>
<div class="sect3">
<h4 id="loader-exceptions"><a class="anchor" href="#loader-exceptions"></a>15.5.4. Loader exceptions</h4>
<div class="paragraph">
<p>cache2k is able to cache or suppress exceptions, depending on the situation and the configuration.</p>
</div>
<div class="paragraph">
<p>If an exception is cached, the following behavior can be expected:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Accessing the value of the entry, will trigger an exception</p>
</li>
<li>
<p><code>Cache.containsKey()</code> will be true for the respective key</p>
</li>
<li>
<p><code>Cache.iterator()</code> will skip entries that contain exceptions</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="listeners"><a class="anchor" href="#listeners"></a>15.5.5. Listeners</h4>
<div class="paragraph">
<p>Asynchronous events are delivered in a way to achieve highest possible parallelism while retaining the event
order on a single key. Synchronous events are delivered sequentially.</p>
</div>
</div>
<div class="sect3">
<h4 id="entry-processor-2"><a class="anchor" href="#entry-processor-2"></a>15.5.6. Entry processor</h4>
<div class="paragraph">
<p>Calling other methods on the cache from inside an entry processor execution (reentrant operation), is not supported.
The entry processor should have no external side effects. To enable asynchronous operations, the execution
may be interrupted by a <code>RestartException</code> and restarted.</p>
</div>
</div>
<div class="sect3">
<h4 id="cache-getconfiguration"><a class="anchor" href="#cache-getconfiguration"></a>15.5.7. Cache.getConfiguration()</h4>
<div class="paragraph">
<p>It is not possible to retrieve the additional effective cache2k configuration with this method.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="performance-2"><a class="anchor" href="#performance-2"></a>15.6. Performance</h3>
<div class="paragraph">
<p>Using the JCache API does not deliver the same performance as when the native cache2k API is used.
Some design choices in JCache lead to additional overhead, for example:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Event listeners are attachable and detachable at runtime</p>
</li>
<li>
<p>Expiry policy needs to be called for every access</p>
</li>
<li>
<p>Store-by-value semantics require keys and values to be copied</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="compliance-testing"><a class="anchor" href="#compliance-testing"></a>15.7. Compliance Testing</h3>
<div class="paragraph">
<p>To pass the TCK tests on statistics, which partially enforce that statistic values need to be updated immediately.
For compliance testing the following system properties need to be set:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>org.cache2k.core.HeapCache.Tunable.minimumStatisticsCreationTimeDeltaFactor=0</code></p>
</li>
<li>
<p><code>org.cache2k.core.HeapCache.Tunable.minimumStatisticsCreationDeltaMillis=-1</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Since immediate statistics update is not a requirement by the JSR107 spec this is needed for testing purposes only.</p>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 1.0.2.Final<br>
Last updated 2016-12-21 20:55:54 ICT
</div>
</div>
</body>
</html>